|
If I understand QueueUserAPC() correctly, what it does is attach a function that needs to be executed to a thread currently executing WaitForSingleObjectEx(), and then if that thread can be be signaled (bAlertable = TRUE), tells that thread "break out of your wait, execute my function, and then continue execution at the line right after the wait".
Is that more or less what it means?
Allow me to ask another question in parallel (no pun intended ):
Are there any CriticalSection-like or Mutex-like objects that can be released from any thread (doesn't have to be the thread that currently owns the CS or Mutex) without giving an error and failing to release?
MODIFIED:
It seems to me, for my second question, that CreateEvent would be the ideal solution for objects that can be waited upon, and that can be changed. Now this makes me think... why would I use a mutex (lots of overhead), or a critical section (a bit of overhead), when I can just use an event that is more flexible (allows me to signal/unsignal from any thread)?
MODIFIED AGAIN:
Nevermind, I realize the stupidity of my question, given that events must be manually set / reset, so signaling an event would cause everything waiting on it to pass through (when you only want to let one go through at a time).
-- modified at 19:42 Sunday 17th June, 2007
|
|
|
|
|
Acccording to the Microsoft Specification, WaitForSingleObject releases all threads simultaneously when the object waited for is released. If this happens on a network, each machine continues running at it's own speed, running the Remaining threads.
On a Network, All threads will be released simultaneously.
On a Single Machine, All threads will also be released simultaneously, but there is then a Scheduler which will allocate Time Slices. It can only release one thread at the time, and there is no saying to which thread it
will be.
I Think you should re-think your design, but if wakening up to order is
important I suggest that you should have More 'WaitForSingleObject'
calls to Implement your ideas
The Bottom Line is: There is NO guarantee about any following order of re-awakening threads by the operating system!! AND THAT IS GOOD
If this happens on a single machine, there is No Way of predicting which will happen first. At Any Rate if you execute a WaitForSingleObject, your thread waits,and potentially NOTHING you acquired before that call is still usefull.
Keep in mind that in theory, WaitForSingleObject() can wait for years!!
So, When it wakes up, it is important that it is followed by code which re-establishes por Updates what happened before the call, and re-establish the situation, before taking action.
LateNightsInNewry
|
|
|
|
|
Well, the original question (and design I had in mind) failed miserably after looking at a few different reasons why, so I scrapped it and made one that not only has far less synchronization (+ for performance), but also zero thread polling (another + for performance), and should work.
What I wanted to do was, if I had 3 worker threads, make the 3 threads not waste much CPU cycles if there was no work left in the queue. There are many ways of doing this and I label the first two as stupid ways (brute force, poor design), the next one a smarter but not smart way, and the last one, the best method, in my opinion:
1 - Continuous polling of the work queue for work
This wastes tremendous amounts of CPU cycles when none should be used. In theory, this is fine, if the only work you do is through the work queue, but using dedicated threads to do all the work in your program, be it big or small, is a bad idea in the first place and won't happen.
2 - Continuous polling of the work queue with a sleep timer
This wastes far less CPU cycles on polling as the thread sleeps for a little while before re-polling. The major disadvantage (and a big one at that), is the latency induced by thread sleeping. In the worst-case scenario, if all of my threads have a sleep timer of half a second, and they all sleep at the same time, work that gets called in that time may wait half a second before it can be processed. On my 2.2 GHz dual core machine, that's potentially 2.2 billion clock cycles wasted. In practice, it will be less, but you can see why this is a bad idea for a high-performance design.
3 - Blocking with critical sections / mutex
In theory, this one actually looks OK. When there is no more work, all I have to do is check a boolean value and immediately enter the critical section from the first worker thread that gets to the point where it's looking for more work and there is none. All the other worker threads that reach that point will not proceed further. This, however, means that you have to handle the case of at least one thread making it through the critical section and looping forever, wasting 100/n percent of CPU cycles (theoretically, where n is the number of active threads and where all threads have equal priority).
4 - Blocking with manually set events
The current method that I use to do this -- I'm unsure of the overhead on an event, but I would guess that it's less than that of a critical section or mutex. I've seen an article where they show acquiring/releasing critical sections have an overhead of around 40-100 cycles, and the same for mutexes is around 750-2500 cycles. I will have to double check these claims, but it comes from this article. With events, the code is simple and threads do not have to poll.
Well, that's my analysis of it... feel free to correct any incorrect assumptions I've made out of lack of experience.
-- modified at 22:17 Sunday 17th June, 2007
|
|
|
|
|
It seems like you've cracked it. In some situations Critical Sections can in fact be the least expensive synchronisation objects but in your case Events do sound better, certainly better than polling Good luck with it.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
Sorry for the Delay.
I do not know what your application is about, but observe as follows_-
Synchronisation Objects (Mutexex, CriticalSections et al) are there for one reason only, and that is to regulate access to shared resources (i.e. Data!)
A Process with threads which do not acess resources shared between threads can run quite successfully without any synchronisation objects. There are many good books available which discuss this subject. From what I gather from your reply, you seem to have an Outside Project which provides data sporadically. WaitForSingleObject(...) was invented for this! You create a Named AutoReset Event with CreateEvent(...) in the Process which generates the data.
When Data is Generated, you Set the Event.
In the program that has to process the data, you open an event of the same name! Then you wait for the event to occur (By set Event in the Other Program)to fire your Code.
Hope this is helpfull
LateNightsInNewry
|
|
|
|
|
how to print a Pictrue(.bmp、.jpg) in Zebra Printer ?
how to transform the Pictrue(.bmp、.jpg) to the Cmd of ZPL II ?
help me!
help me!
help me!
My E_Mail:h_boy2008@163.com
Thanks,Thanks,...,Thanks!
|
|
|
|
|
I have the Zebra ZPL II manuals and spec at work, so not with me today. You can download up to 4? bitmaps by encoding them as hexidecimal numbers in the text of the ZPL file (whacky I know). JPEGs would need to be converted to straight bitmaps before downloading as Zebra doesn't have a JPEG decoder to my knowledge. Email me tommorow (Monday) at mfaithfull@btopenworld.com and I'll be reminded to send you a sample.
Not too many Zebra users out there. I'm curious what you use it for?
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
The ZPL information you need can be found at this link www.servopack.de/Files/HB/ZPLcommands.pdf
On pages 70-75 it describes downloading and using graphics.
A graphic within a ZPL file might look like this
~DGR:85DB1DA4,00360,012,
1FFFFF03C07C000780,1FFFFF03C07C000780,1FFFFF03C07E000780,1FFFFF04C07F000780,1E
000003C07F000780, 1E000003C078003F80,1E000003C07FC00780,1E000003C07BC00780,1E00
0002C07BE00780F0,1E000003C079F00780F0, 1E000003C07807C780,1E000003C078F80780F0
,1FFFFC03C0787C0780,1FFFFC03C0783C0780,1FFFFC03C0683E0780,1FFFFC03C0781F0780,1E
000003C0780F0780,1E000003C0780F8780, 1E000003C078F00780F0,1E000003C07806C780,1E00
0003C07803E780,1E000003C07801F780,1E000003C07800F780,1E000003C07800FF80,1E0000
03C078007F80, 1E000003C07F800780,1E000003C078003F80F0,1E000003C078002F80F0,1E00
0003C078000F80F0,1E000003C078000F80F0,
And the command to place one on a label like this
^FO473,179^XG85DB1DA4,1,1^FS
DG downloads the graphic into the printer’s memory.
XG recalls the downloaded graphic from the printer’s memory into your label.
You can find the details of all the commands in the manual I linked to. (Requires PDF reader)
I don’t know much more than this myself. ZPL is certainly very strange
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
hi i am creating a msi set up project in visual studio. i have to insert the installation path in regedit also. how to do this. pls help me. im new bie to visual studio
Arise Awake Stop Not Till ur Goal is Reached.
|
|
|
|
|
i have just finished compiling my application and everything is in order, but when i run it to test the different features, there is a runtime error...and it deals with access violation, hence a pointer issue. i need help fixing this and following is the call stack:
int wNode::getId() <br />
{<br />
return id;<br />
}
-----
int* workflow::getIDArray()<br />
{ <br />
int total = numNodes; <br />
int i = 0;<br />
int* IDs = new int[total];<br />
wNode* temp = first;<br />
while (temp != NULL) {<br />
IDs[i] = temp->getId();<br />
if (temp->getHasLeft()) {<br />
IDs[i+1] = temp->getLeft()->getId();<br />
i++;<br />
}<br />
temp = temp->getNext();<br />
i++;<br />
}<br />
return IDs;<br />
}
-----
<br />
int* wf_ids = dg_scenario::dg_workflow->getIDArray();<br />
any help would be greatly appreciated..i am new to c++ and thus am having a hard time tracing my steps and finding which line has the faulty pointer issue.
NOTE: the application has no compiler errors.
--
dg
|
|
|
|
|
You've left too much out to give you any real help. What is numNodes? Exactly which line in getIDArray caused the access violation? You should run your app under the debugger, put a breakpoint on the first line in getIDArray , and step through it, looking at variables.
p.s. It's much easier to read code if you use the "pre" tags.
|
|
|
|
|
numNodes is a data member in the workflow class that keeps a count of the number of nodes in the workflow.
here is the complete runtime error:
First-chance exception at 0x004fd341 in spring.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd.
Unhandled exception at 0x004fd341 in spring.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd.
the line it takes me to is:
int wNode::getId()
{
return id; <<<<----------------that one
}
is there anything else you need??
i tried putting a breakpoint in the first line of getIDArray but what do you mean "step through it"?
--
dg
|
|
|
|
|
Typicaqlly Access violation reading location 0xcdcdcdcd means you read Uninitialised Data. This is how the Compiler (Debug Version) Padds Newly Allocated Data.
LateNightsInNewry
|
|
|
|
|
I give the following advice about once a month (recently every few days); it often helps me track down the nastier heap errors:
Try enabling the page heap[^] for your process. Follow these steps:
1. Download and install WinDBG[^].
2. Select “Start”->“All Programs”->“Debugging Tools for Windows”->“Global Flags”.
3. Select the “Image File” tab.
4. In the “Image: (TAB to refresh)” edit control enter the name of your app then press TAB. Just the name with the extension; not the full path.
5. Tick the following:
- “Enable page heap”
- “Enable heap tail checking”
- “Enable heap free checking”
- “Enable heap parameter checking”
- “Enable heap validation on call”
- “Create user mode stack trace database”
6. Press “Apply”.
7. Debug your application. Any debugger will do but with WinDBG you have access to the stack traces of allocations via the !heap –p –a command, for example. When a heap problem is detected a breakpoint will be generated.
8. When done un-tick all the options you ticked, press “Apply” then dismiss GFlags. This step is important as if it’s skipped all applications named as entered in step 4 will run with the page heap enabled.
Note that when using the page heap your application will run much slower than normal and consume way more memory. It’s good to have a beefy machine to do such tests; and such tests should be ran regularly on all applications you develop as part of regular testing activities. If I find a part of my application that’s too slow with the page heap enabled I optimize the memory allocation in that region.
Steve
|
|
|
|
|
Question
What is the reason for those nasty heap problems. I Still use VCPP5.00 and have had very very few of these problems. One Process was closed down recently for other reasons after 1100 days running on Win98! Total Memory Leaks: 8096 Bytes. What's Happened ?
LateNightsInNewry
|
|
|
|
|
i am trying to draw 2D polygons and lines in C++ and i was wondering what libraries i can use. also are there any good tutorials i can refer to...
my end goal is to output a 2D square with a background color and some text inside of it...
any ideas/suggestions..? i have tried google and cant seem to find good resources..
thanks in advance.
--
dg
|
|
|
|
|
You can use GDI+. I've used it to create a form with a chart control (basically inherits panel) in Managed C++, and it wasn't really that hard to pick up. You can also use GDI+ with native code though.
|
|
|
|
|
nice..thanks!! this is probably a stupid question but after you download the .dll file off the ms website, where do you save it so all the classes work properly in my app??
--
dg
|
|
|
|
|
I am actually having trouble using GDI+ without getting compiler errors..
i have all my header files including GdiPlus.h in: C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include
i have the GdiPlus.lib in: C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Lib. i have also added GdiPlus.lib file in the additional dependencies of my project.
i have the .dll file stored in my local app directory..
when i #include GdiPlus.h, i get 107 compiler errors some of which are like the following:
1>C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\GdiplusEnums.h(28) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\GdiplusEnums.h(28) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\GdiplusEnums.h(520) : error C2146: syntax error : missing ';' before identifier 'ObjectTypeIsValid'
1>C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\GdiplusEnums.h(520) : error C2433: 'BOOL' : 'inline' not permitted on data declarations
1>C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\GdiplusEnums.h(520) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\GdiplusEnums.h(523) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\GdiplusEnums.h(548) : error C2065: 'META_SETBKCOLOR' : undeclared identifier
1>C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\GdiplusEnums.h(548) : error C2056: illegal expression
1>C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\GdiplusEnums.h(549) : error C2065: 'META_SETBKMODE' : undeclared identifier'
.. i am completely lost. any help on fixing this and enabling me to use GDI+ in my app without any trouble will be greatly appreciated.
--
dg
|
|
|
|
|
Sorry, I can't really help you out with setting up the environment for using GDI+ in native C++ as I've never done it myself -- I've only used the managed version.
As for your compiler errors, error C4430 typically indicates that you're missing the definition of a certain struct/class. The line number will tell you which one in particular it does not recognize, that you're trying to use.
|
|
|
|
|
Hello
How can i change the CLSID and progid for already existing projects.Should i generate this for each project using guidgen.exe?I want to be able to load the dlls from a different target path, as a seperate plugin.is it sufficient to change the clsid alone or should progid needs to be modified as well? What will be the efficient way to do this.
Thanks
|
|
|
|
|
I think the only practical way to do this is generate a new CLSID and paste it into the IDL file manually. Followed by a rebuild all. I have done this in the past to seperate different builds of COM objects.
Best Wishes.
-Randor (David Delaune)
|
|
|
|
|
Thanks for the reply David. Can i similarly change in the .rgs file associated with each project and do a rebuild all.The ProgID should not matter for loading dlls with same name from different target path right. Or can i manually change the last field of Project.ClassName.1 to Project.ClassName.2 in the .rgs file.I think the version independent progid can remain the same.
Thanks!
|
|
|
|
|
Yes, I forgot to mention that the .rgs files should also have the CLSID replaced. This is required to register the DLL and its interfaces. Technically the ProgID and the filename does not matter as long as all GUIDs have been changed. In fact; this why COM was invented (The cure for DLL Hell) although it failed miserably.
For the sake of completeness:
WinSxS (Side-by-Side) is Microsofts latest cure for DLL-Hell. http://msdn2.microsoft.com/en-us/library/aa374224.aspx[^]
Best Wishes,
Randor (David Delaune)
|
|
|
|
|
How is proxystubclsid generated?I find that in my application proxystubclsid is same as proxystubclsid32 and a default (same)value is used for all interfaces.
|
|
|
|
|