|
Hi,
If CSemaphore::Release() is called multiple times by the same thread, does it increase the count each time, or does CSemaphore only keep a count of the number of DIFFERENT threads that have called Release?
I am working on some code where one thread calls Release() each time it adds stuff to a queue, expecting a worker thread to fire the correct number of times to remove stuff from the queue. The code doesnt work properly and I suspect it is fundamentally flawed.
Any ideas?
Tony
|
|
|
|
|
softwaremonkey wrote: If CSemaphore::Release() is called multiple times by the same thread, does it increase the count each time
Yes, absolutely.
Unless there's something wrong with the CSemaphore class since a semaphore is supposed to work that way.
softwaremonkey wrote: I am working on some code where one thread calls Release() each time it adds stuff to a queue, expecting a worker thread to fire the correct number of times to remove stuff from the queue. The code doesnt work properly and I suspect it is fundamentally flawed.
This is a commonly used technique that is both efficient and a school book example of good asynchronous design. About the "fundamentally flawed" part I can assure you that it's not, at least not in the aspect of design.
However, I don't use the CSemaphore class. I favour to use ::CreateSemaphore(...) , ::ReleaseSemaphore(...) and ::CloseHandle(...) .
Can you explain more about the code where you push and pop your object to the queue and how you wait on the semaphore? How about some small code snippets, preferrably within <pre> tags...
You can also read about it here[^].
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
I agree with Roger 100%. Using a semaphore this way is very efficient.
The only thing additional that comes to mind (that you may/probably have considered) is the
possibility of reaching the maximum count on the semaphore object. This needs to be addressed
when calling ReleaseSemaphore, otherwise you could (depending on the worker thread
implementation) end up with queued data that the worker thread will never know about.
Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
|
|
|
|
|
Thanks Guys.
I have used native API semaphores for this purpose before but I didnt know if there was something 'odd' about the CSemaphore class because the MFC documentation says it "allows a limited number of threads in one or more processes to access a resource". I was just making 100% sure that it worked the same as the native Windows semaphore. Clutching at straws really, the code isnt mine and I was told it didn't work. I have tried it in isolation and it appears to work fine so I suspect that it only falls over when integrated into the rest of the code. There are, as you suggest, unprocessed items building up on the queue but the max count for the CSemaphore is 200000 so I would not expect this limit to be reached as the queue is much smaller than this an we cannot get more than 18000 items at once in any case.
Thanks for the info though, it helped me to avoid the 'red herrings'
Tony
|
|
|
|
|
As I understand it your problem has not been solved yet, right?
softwaremonkey wrote: unprocessed items building up on the queue
This implies that the code that is waiting on the semaphore and supposed to be released, doesn't get released. Is this really how it is? How do you issue the wait on the semaphore, from where and from which thread?
Have you, or anyone else, played around with the thread priorities preventing the thread from running?
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Hi Roger,
Thanks for the reply. At this point, when I test the code it works fine, but the guys who did the field testing have reported that if more than one message is queued within a short period of time, only one of them gets processed, leaving messages on the queue. I am unable to replicate this here, it all works fine. The worker thread is set to THREAD_PRIORITY_BELOW_NORMAL. There are only two threads involved, one which adds messages to the queue which then calls CSemaphore::Unlock(). Meanwhile, the worker thread is blocked with CSemaphore::Lock() and so it bursts into action to remove and process the message(s) as they are added. I believe that the code is OK and that there is something different about the way it is being used in the field. Until I see it for myself, I cant really say what is going wrong.
Cheers,
Tony
|
|
|
|
|
It's not clear to me how you protect your queue.
Now I also remember why I don't use the CSemaphore class; the Lock/Unlock semantic is confusing. With an ordinary semaphore you don't "lock" anything, it would require a special case semaphore called a "binary semaphore" that can only have two states: signalled or not signalled. This is also known as a mutual exclusion (mutex).
The article I referred to in my first post describes this.
I've been thinking about writing an article on this for about a year but haven't found the time yet.
You have to use both a semaphore and e.g. a critical section. The critical section is for protecting your data to give exclusive access to one thread at a time, preventing data corruption.
It also seems to me as if there are more than one object in the queue when the code execute that retrieves the queued objects, only the first object will be popped.
If this is the case, the example below will fix that.
The code that push objects into the queue should look something like this:
long nObjectsAdded = 0;
CQueueObject* pObj = NULL;
::EnterCriticalSection( &m_csQueue );
while( pObj = GetNewObject() )
{
m_Queue.push( pObj );
++nObjectsAdded;
}
::LeaveCriticalSection( &m_csQueue );
::ReleaseSemaphore( m_hQueueSemaphore, nObjectsAdded, NULL ); The scheme above will let you add several objects to the queue without being forced to allow the reading thread to pop objects from the queue before adding a new object. Also think about where the synchronization functions are called. I don't want the other thread to be unleashed simply to be blocked on the critical section, it wouldn't make sense and would be inefficient. This is why ::ReleaseSemaphore() is called after the critical section is left.
But to make it work correctly you have to implement the part that gets the object from the queue in the same way. Something like this:
while( !bStopRunning )
{
::WaitForSingleObject( m_hQueueSemaphore, INFINITE );
::EnterCriticalSection( &m_csQueue );
CQueueObject* pObj = m_Queue.top();
m_Queue.pop();
::LeaveCriticalSection( &m_csQueue );
} ::WaitForSingleObject(...) will be released once for every time ::ReleaseSemaphore(...) is called, i.e. once for every object in the queue given the example above.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Hi all.
In my application I am trying to copy an html page from one temp location to another location specified by user.
I am using CopyFile() API to copy html pages.
But I need to explicitly carryout the image copying along with the .html page copying.
Is there any other API which copies all the images from particular html pages implicitly when I copy that html page?
Thanks
-- modified at 3:27 Wednesday 18th April, 2007
-- modified at 3:28 Wednesday 18th April, 2007
Sameer Thakur
|
|
|
|
|
What happen if you use of SHFileOperation ?
|
|
|
|
|
I created one windows form and placed text box.
my working environment:Vc++.net.I want to retrieve the content of that textbox and assign to variable/string.
please help...I am new to .net programming.
Thanks in advance
Ashok
|
|
|
|
|
Try the following forum: .Net Framework[^]
String^ abc = TextBox1->Text;
Regards,
The only programmers that are better than C programmers are those who code in 1's and 0's.....
Programm3r
My Blog: ^_^
|
|
|
|
|
It was better you asked here[^]
|
|
|
|
|
hi,
I am using Quark XDK 6.1 function to print Quark pages to PDF.while printing if the
images in the Quark pages are not in the proper path.Quark will prompt
image missing Dialog Message.
After clicking OK in the dialog only the printing will continue.
I would like to Suppress the "Missing Picture Dialog Box - Warning Message ".
for this i try to get the Dialog id in the PrintCall back function but i failed in that.
can anyone tell me where i should call the function xd_getdlg(&gImgMissingDlgID);to get the Dialogid.
or Is there any other way to achieve it?
OS: WINDOW 2000,XP
XDK: QUARK XDK 6.1
creation of WIN32 DLL in vc++ 6.0
Please provide any infomation that you think may help me to resolve it.
Regards,
Karthick
|
|
|
|
|
hi all,
I tried to create a win32 application with sockets
I have included <winsock.h> and called WSAStartup() API function.
But I got a link error:"unresolved external symbol _WSAStartup@8"
Please give a help
Thanks in advance.
SYAMLAL
|
|
|
|
|
QuickInfo
Windows NT: Yes
Windows: Yes
Windows CE: Use version 1.0 and later.
Header: Declared in winsock2.h.
Import Library: Link with ws2_32.lib.
Regards,
The only programmers that are better than C programmers are those who code in 1's and 0's.....
Programm3r
My Blog: ^_^
|
|
|
|
|
thanks to all who took interest.
I thought this lib should be included in case of MFC only, and so I didn't try it out.
Thanx a lot.
SYAMLAL
|
|
|
|
|
SyamlalS wrote: thanks to all who took interest.
np (No Problem)
Regards,
The only programmers that are better than C programmers are those who code in 1's and 0's.....
Programm3r
My Blog: ^_^
|
|
|
|
|
Specify the required lib file Ws2.lib
Regards,
Paresh.
|
|
|
|
|
Requirement section for this API mention Ws2_32.lib as library. You need to link that.
Prasad
MS MVP - VC++
|
|
|
|
|
|
Programm3r wrote: WIN32 Console application
You need to start with an MFC (not Win32) GUI (not console) app.
|
|
|
|
|
Well Im a student and yesterday appeared in external examination (Lab Test)for "Data Structure Using C".
I was asked to write a program to do following thing :
1.Read Unsorted data(Rno & Marks)from an existing data file.
2.Display Unsorted data.
3.Using Linked list, sort the data on the basis of Rno.
4.Display Sorted data in increasing order.
5.Display same sorted data in decreasing order.
6.Search a particular record on the basis of some key(Rno).
In response what i did was
1.Make a write() and read() function in C using fopen() and fread() and fwrite().
2.Create a singly Linked list and while reading data in read() it used to fill it in the same way as it was stored on file.
3.Display the unsorted list.
4.Use bubble sort to sort the list and display it in Increasing order.
5.Searching on the basis of Rno.
Sorry for posting such a huge amount of text but i wanna make things clear.
My teacher told me that I should have put data into linked list in ordered manner while reading from file i.e. somewhat Insertion sort. I agreed but argued on the fact that question paper didnt mention to force me to use the best technique so i was free to use any sort.
But the nutshell was that i was failed and was told to appear again for the test next year.
Can any tell whether im right or wrong so that i can go to my HOD for the same.
Spread wat u Know!
|
|
|
|
|
Serious answer: Sounds to me like you got shafted
Humorous answer: One of your superiors changed their mind about the spec, and then blamed you? Welcome to the world of software.
|
|
|
|
|
Maybe I am missing something here, but requirements had 6 steps and you only listed 5.
Did you remember to display it in descending order as well?
I would hardly argue they could fail you if yousupplied all required steps, since there are no specifications regarding performance, system limitations, or otherwise.
If I had said this would be a high load system and this would be done several times per hour, I might have had issue with the bubble sort and singly linked list.
I think you would have found you had trouble with the descending display, unless you 'unbubbled' your items to reverse their order - basically you went through your list sorting it twice, then.
|
|
|
|
|
I must say "thnx" to the writer of article "Calling Conventions Demysified".
It is such a good article, i mean im a student n i feel it is must for every c programmer.
But im confused with what was written in first few lines :
"the value is returned in EAX register."
I mean no problem with basic types but how this statement fits fine for structures like:
struct abc
{
int x;
float y;
};
struct abc fun(void)
{
struct abc x;
x.x=0;
x.y=1;
return x;
}
Spread wat u Know!
|
|
|
|