I have a lttle a problem....i.e I have made a multi-downloader of file...

and use a Mutex ....and of course also API

WaitForSingleObject ....

and sometime, from time to time, the second thread doesn't want to stop...i.e properties of Mutex don't want

to re-pass to the principal thread...

To find that...try several files to download...and generally big-one above 5 Mbytes...you'll see
my problem...

If some-one of you find my error, please send me a answer...


Here is the file:
Posted on 2003-07-11 11:06:46 by gerard
I'm not quite sure of the problem (and I'm not downloading a 5 megs file just to test it, sorry :grin: )...
What do you mean "the thread won't stop"? Exactly what are you using the mutex for? It seems to be used only in the proc that updates the progress control... :confused:
Posted on 2003-07-11 11:29:52 by QvasiModo
Yes Mutex is in a procedure which serves only to the ProgressBar ...

it serves to let passed thread the ones behind the others....i.e to limit interferences...

The problem is ...and I repeat me...in WaitForSingleObject because it transferts properties of Mutex to an another thread...

Please try to download several file and you'll see...and what I wanted is to find a stratagem
to palliate at this problem...

Posted on 2003-07-11 11:46:19 by gerard
I don't have experience with mutex, and I would really hate such. Whenever possible, I always use code that I know by heart, and you can replace mutex stuff with XCHG.

I have been using XCHG for 1 year, and it absolutely never let me down. My program never crashed or misbehaved for object locking thanks to using my own mutex, even though it has 4 threads that have high priority and each of the threads gets its timeslice every 10ms.
Posted on 2003-07-11 12:36:34 by Ultrano
Sorry, still not following you...

I don't understand many things about your code:

1) Why using a mutex? I'm not sure exactly what you're trying to synchronize, and your code is not commented...

2) Why opening the mutex with OpenMutex when you already have the handle?

3) Why not sending a message to increase the progress bar position, instead of setting it's absoulte value? I think there's a message for that, PBM_SETPIT if I remember correctly.

4) Why do you use the same global variable hMutex for all threads at the same time? Doesn't that cause the threads to overwrite each other's values?
Posted on 2003-07-11 15:56:11 by QvasiModo
It took me a long time to answer because I live in France...there is a gap of 6 hours between both...

It is a good advice...and,of course, I followed it...I removed, therefore, the use of a Mutex......Normally, all is well which finishes well... but prog doesn't always work correctly again...

But I thought a lot about the problem I had... However the problem was not here and was in another place...a problem
of algorithm....i.e in the second thread...when buffer loads the last (remainder) of bytes (under 4096 bytes)....

I am going to explain how works a Mutex...

Nobody is the owner of a Mutex...when this-one is signaled...and a Mutex...have only one owner at each time...
but can change of owner...In my program, principal thread gets the Mutex......then after Mutex goes to thread1 and thread2 in an uncertain way...
and at last returns to principal thread....
Nothing more simple...

If somobody finds my error....perhaps calculus of

nSize1----> 0FFFFF000 and nSize...

Posted on 2003-07-12 01:40:04 by gerard
Yes I have forgotten to give you more informations, the more serious, from the site of Microsoft .

You have to click on this link to access Mutex_Objects ...

I shall be happy if you'll find this clue very interresting...



?The two great and pricipal actions of the mind which are most frequently considered...are these two:Perception or thinking; and volition or willing. The power of thinking is called Understanding and the power of volition is called the Will; and these two powers or abilities in the mind are denominated Faculties.? (Locke, Essay Livre I, ? VI.).
Posted on 2003-07-12 10:58:50 by gerard
Ok, I know now how your algo works:

- Get the file size
- If it is small, download in one chunk with DownloadProc
- If it is big, split in two slices, and download in separate temp files in \Temp (create the folder if necessary)
- After downloading the two slices, merge them in one file.

I had trouble understanding because I had never used a Mutex before, except for single instance application code. I prefer using events and messages, so I never tried mutexes and semaphores.

I've been googling a while, and found out how to improve this algo, based on how GetRight, DAP, KaZaA and other programs work. It involves passing parameters to a thread, using event objects, file mapping (Iczelion's tutorial 13), and growing a file size without writing to it.

First, the threads:
Well, you currently have 2 different procs for each thread. This could be inconvenient if you want to use more that this two threads in the future (imagine trying to use 10 threads :( ). The best way to solve this is using a single DownloadProc for all cases.

hEvent dd ? ;will use to pass params
hMap dd ? ;use for file mapping (see below)
dwBegin dd ? ;beginning of slice to download
dwEnd dd ? ;end of slice to download
;etc... any other params you might want to pass

dap_params DAP_PARAMS <>

To call your threads:

; First we create the event object and set some params
invoke CreateEvent,0,0,0,0
mov dap_params.hEvent,eax
mov eax,hMap ;this is your map handle
mov dap_params.hMap,eax
; so on, for all the params that are the same for all threads

; Then, a loop:
mov ecx,number_of_threads
push ecx

; set all the other params here, that are different for every thread
mov dap_params.dwBegin,beginning_of_slice
mov dap_params.dwEnd,end_of_slice

; create the thread
invoke CreateThread,0,0,offset DownloadProc,offset dap_params,0,offset threadID

; wait until it has copied the params to stack
invoke WaitForSingleObject,dap_params.hEvent,INFINITE

pop ecx

; Now, close the event object, since we're not using it anymore.
invoke CloseHandle,dap_params.hEvent

; In your download proc:
DownloadProc proc lParam:dword
local myparams:DAP_PARAMS ;this is where we copy the params in stack

; copy the params to stack
mov eax,lParam
lea edx,myparams
mov ecx,sizeof DAP_PARAMS / 4 ;DWORD aligned! if not, you'll have to use bytes
push dword ptr [eax]
pop dword ptr [edx]
add eax,4
add edx,4

;now that we have the data, set the event
invoke SetEvent,(DAP_PARAMS ptr [eax]).hEvent

;... the rest of your code

ret ;it is not necessary to end in ExitThread, just return will do
DownloadProc endp

So, now with the file mapping strategy:
The basic idea is this: once you know how long the file is (FileSize), and how many slices you want (number_of_slices), you divide FileSize by number_of_slices to get how long a slice is (SliceBytes).
The you create number_of_slices-1 threads that download SliceBytes bytes, and a last thread that downloads the rest of the file (FileSize - (SliceBytes * (number_of_slices - 1))).

To write to file, you don't use WriteFile, instead open a file mapping (CreateFileMapping), and then each thread can map a view of the file corresponding to it's slice (MapViewOfFile). To do this, you need the destination file to be already FileSize bytes long, or you can't map. To do this, you have to allocate disk space without writing to disk (so it's faster).

You have to:
- create the destination file (it will be 0 bytes for now)
- move the file pointer past the end of file (SetFilePointer), and set the end of the file (SetEndOfFile):
- then you can map the file.

To extend the file size:

invoke SetFilePointer,hFile,FileSize,0,FILE_BEGIN
invoke SetEndOfFile,hFile
invoke SetFilePointer,hFile,0,0,FILE_BEGIN ;reset the file pointer before mapping

You file will contain garbage at first (whatever was on the disk before you allocated that space). That's why when you take a partial download from KaZaA and try to open it with WinAMP, you might listen fragments of your deleted MP3 files... :)

You can create a temp file first, but you should do it in the same drive and directory as your destination file. This way, the user will not try to open the file before it's finished downloading. When you're done downloading, just close the file and rename it (much faster than rebuilding the target file from several temp files).

Another advantage of using this method is that you will know if there is enough disk space for your file, because SetEndOfFile will return error if there is not enough free space.

As a final suggestion, you could use window messages to synchronize your threads... so if the user presses a "Cancel" button, you can signal the threads to stop. But it's a lot of work, I have never done it (yet).

Now try it, and tell me how you're doing... and I think we'll all like to see your download accelerator posted when it's finished :alright:

Well that was my longest post on this board... :cool:
Posted on 2003-07-15 09:02:30 by QvasiModo
Moi Dorogoi (Russian language) means Darling ----my dear is Dorogoi Moi ....it's for the "flush"....
stop here my little joke....and enter in the subject...

Yes in the folder (with extension zip) you'll find a big stuff very interesting....and two tutorials than I "bissed"....

About the mapping I signal to you, that it is very interresting with Process...and I already
(it's true: not finished) did one program in Visual Basic, you could find it here:
Visual Basic

I think, you will be happy to see your e-mail below the tutorials, the two...

If you have some comments to tell me...don't bother you...e-mail me...or Fax me..(it is also a joke...
but this time french...when two boys live together ...we call that (the Law) a packs...).

Like Madonna, I think I do my best....

Where to find the folder:
Folder to download.

( Where two or more ideas have been often repeated together and the association has become very strong, they sometimes spring up in such close a combination as not to be distinguishable.)
> James MILL <
Posted on 2003-07-23 05:32:27 by gerard
Hey, glad I helped :)
By the way, I've been browsing your webpage... Great tutorials and code! :alright:
And thanks for including my mail address...
Posted on 2003-07-24 08:03:41 by QvasiModo