|
The "official" way to do expression evaluation involves parse trees and reverse Polish notation, but I found a simpler more practical approach: Repeatedly process your list of tokens, making it one step simpler each time by applying a series of rules:
1. If you see the sequence '(', 'number', ')', replace it with just 'number'.
2. For each operator in decreasing precedence, look for the sequence 'number', 'operator', 'number' and replace it with the result of the operation.
If you end up with a single number, that's your answer. Anything else indicates a syntax error in the input expression.
|
|
|
|
|
Hi,
I am still struggling on in Silence with Multiple threads, and See working Code break for no apparent reason following minor Edits.
I have read several articles about it, and, if I take all advice to hart, the answer is "You Can't" The Preferred Method of One Expert leads to grave Demise by another.
I am writing a Dialog Based system where a user Logs In, and, perform certain transactions. I am trying to implement a Controlled Log Out (and return to Base) in the absence of User Activity (Mouse Moves, Clicks, Kb Keys Pressed)
In Adittion, when TimeOut comes Close, a Small ProgresBar+ Message Appears , counting Down, only XX Seconds remaining.
I constructed a New Class, CTimedDialog, and a new App Class, CTimedWinApp. The Latter maintains a list of the m_hWnd of the Dialog Stack, and has a Timer, 1 tick per Second. The 'OnInitDialog' of CTimedDialog (This is a Class that sits between CDialog and the Ultimate UserDialog Class)registers the Class with CTimedWinApp. Upon Time-Out, A Registered Message(WM_TIME_OUT) is '::SentMessage'ed from the timer thread,to the hWnd from the Top of the List, following tru to the bottom, giving each dialog the chance to handle the message, and do a Cleanup (if required), and to close the all dialogs, and, so returning to the Base of the initial menu screen.
In adition, as each Dialog 'Knows' it's timeout value, I set up a separate timer in each CTimedDialog, that initially shows a Progress Bar, and a Text Message to display the remaining time. This timer updates the text with SetWindowText(...) and the ProgressControl with SetProgress(...)
Yes, the Progress Controls had their ranges set.
All worked to perfection when I built a Skeleton Application, of essentially blank Dialogs.
Started to fill in Details, Controls, etc, and the App Clock Ticks are no longer recognised.
Question, Do I have a hard to chase Bug, or, do I do something Wrong.
The Core code involved is quite large, too large to publish here, and covers several files.
I can mail the lot to whoever is interested as a ZIP.
As a Bottom line, there are multiple ways to skin a cat. MFC is capable of multithreading, witness the existence of MS-Office
We need to find the Right way of running Multiple threads in MFC from MS. The guidance for now seems to be: don't
Regards,
Regards
Bram van Kampen
|
|
|
|
|
Bram van Kampen wrote: Upon Time-Out, A Registered Message(WM_TIME_OUT) is '::SentMessage'ed from the timer thread Don't use SendMessage to send messages from one thread to another. Use PostMessage or SendMessageTimeout instead.
While this probably does not solve your current problem it may avoid future problems.
|
|
|
|
|
Bram van Kampen wrote: Started to fill in Details, Controls, etc, and the App Clock Ticks are no longer recognised. That seems unlikely, unless you are somehow blocking them or throwing them away somewhere. Where do you handle the actual tick messages?
|
|
|
|
|
Well,
I also consider it Unlikely, but that is what both Concept mistakes and stupid Bugs are made of.
The Tick Messages are sent to the Application. The Application has a List of Structures, consisting of: the hWnd of the Dialog, the Default TimeOut, and the Current Count. Upon every tick the Top Count get decremented, and, when it reaches 0, a Registered Windows Message, WM_REG_TIME_OUT is sent to all Dialogs, in Sequence. The CTimedDialog primitive answers to this by a virtual OnDlgTimeOut(), which by default ends the dialog by OnEndDialog(IDABORT). If the Dialog ends for "Natural" reasons, the EndDialog() of CTimedDialog Pops the reference to the Top Dialog of the list, and resets the Current Count of the new Top Object to it's Default value. I have used a CRITICAL_SECTION where needed, but did not go over the top with belts and braces.
The Time-Out bar on the dialogs is more of a debug feature than anything else. It assures me that the clock is ticking, and that things did not deadlock.
Thanks for giving me the foothold for assuring me that I am not doing something fundamentally wrong,as other books and autors seem to suggest. (NEVER mix a Worker and a GUI Thread) my Concept is at least not wrong in your judgement. I Start looking for a stupid mistake somewhere.
Timed and Activity based actions are notoriously difficult to debug.
Stupid Mistakes, (and I made many in the past 60 odd years), are the most difficult ones to find.
I'll let you know when I discover what went wrong. I also think that when I get it right, that the subject is of sufficient interest to merit an article.
Regards,
Bram van Kampen
|
|
|
|
|
Sounds fine to me - but then what do I know, I've only been programming for 50 years.
BTW, that other message that you received from me appears to have been a mis-post by the hamsters.
|
|
|
|
|
Well Richard,
Did not mean to upset you. My native language is Dutch, and, I Don't Do Sarcasm, but Do do Self depreciation.
From what you wrote, I concluded that in your valued judgement, my Basic design is possibly right, but that I made a stupid mistake somewhere in the code base. I responded along these lines
From your response, I think that you think that I was sarcastic in my reply, I was not, I was genuine and tried to reflect on the fact that I am genuinely aware of my own fallibility, and need to start chasing down a stupid mistake I made, in stead of the whole concept being wobbly.
In my experience GDI debugging issues break down into a variety of issues. A first one is, expecting the GDI system to do things that it fundamentally can not. In that case, trying to debug is flogging a dead horse. The best thing there is often to start again, and salvage what you can.
Many bugs are what I call 'Stupid' ones. Hard to Find, but, when found, trivial to resolve. an == ipv an =, or viceversa, Missing or misplaced Brackets, calling a wrong but similarly named function, etc. Well I'm sure you've been there, and can add to the list. In short, things that compile right, but act differently than as intended by the author.
I was grateful that you condoned the model I had, and by extension suggested that I must have made a 'stupid mistake' somewhere. That is far better news than that 'Your Model is Wrong'.
I make 'Stupid mistakes' on a semi regular basis. (I try to avoid the habit for as much as I Can) I think Most Programmers do the same. That's what debugging is for.
Bram van Kampen
|
|
|
|
|
Uh-oh, language problems again.
My sincere apologies, you certainly did not upset me, and I am sorry if my reply sounded sarcastic. When I said "what do I know, I've only been programming for 50 years.", I was being, or trying to be, ironic. The point was supposed to be that even after that much time, I still have a lot to learn, and still make stupid mistakes every day.
As to your problem, I doubt that you have made a stupid mistake, more likely just one of those infernal bugs that are difficult to track down. Lost coun t of the times ...
|
|
|
|
|
Language Problems again indeed.
Sorry for getting the Wrong end of the stick. I call those things 'Stupid'. That reflects my feeling when, after two days stepping trough code into ever deeper levels, I find in the code I wrote a few years ago, deep inside the bowels of working code something like:
if(abc=PQR){ do this }else{ do something else}
Worked fine for three years, Changed something, which (Although I long forgot the details of the How and should call the else,(which of course never happens), and the program breaks at run time.)
You know the run yourself! Working Code, Go tru the documentation, and even when you look at the offending line, you can still overlook it. It Must be There you say. Let's look at the Assembler Code! Hey, the Whole 'if' and 'else' statement have no Code.
At the same time, it worked for years.
You Doubt Compiler Settings, did I have a bad #define somewhere that caused this. Then it dawns! '=' in stead of '=='. (Or some error of that kind)
Then is my bodily reaction to feel Stupid. First of all for not properly testing years ago, but then again, I'm on my own, and there is often pressure of time. One needs to produce something that works, and Our own shop, the main user of the software is often gagging for it. Secondly, for making the typo in the first place. It was not the fact that I did not know the difference between, in this case '=' and '==', but there are other typo's.
Thirdly for not believing that the Compiler compiled correctly. Yes, the beast is near coming of age at 19, but, it is trusty,
and I am aware of it's vagarities.
The Other option is always that I have a Concept Wrong. Something that worked, in the past, but the strict rules were not followed, and the failure to follow the rules comes home to roost. This can ultimately mean re-starting from the beginning, and flushing existing code.
What's new for me is multithreaded programming. I've read quite a few articles on it, and the do's and dont's are so scary and forbidding, one would conclude that multithreading in MFC is all but impossible. At the same time MsOffice95 uses it liberally.
The point is, that I'm fledgling to write stuff like that, and when things go wrong is: Was it a Typo, or, did I fall in One of the Pitfalls. Then there is lack of Information.
Does the Windows Timer Stuff start a New Thread, (if so, of what kind, GUI or Worker), or is it a kludge in the Message System.
At least Peace between us has broken out again. Sorry again that I ever thought different.
BTW always feel free to email me. We may have things in common and experiences in life to share.
Regards
Bram van Kampen
|
|
|
|
|
Yes, been through that more times than I care to remember; but that's all part of the fun.
|
|
|
|
|
Bram van Kampen
|
|
|
|
|
The fact you have been programming for years and the weird behaviour leads me to ask. The usual trap for someone of that experience and first moving into multitasking is not knowing when to use the word "VOLATILE" in front of a variable declaration.
So lets ask the obvious do you know when you have to use "VOLATILE" in some instances and why. The corollary to that is are you sure you haven't missed any in your code given your symptoms.
In normal single thread work you may only have ever run across the word when directly accessing hardware ports but it is far more critical in multitasking. You get symptoms very similar to what you describe.
In vino veritas
|
|
|
|
|
Well,
I know and use 'volatile' (where appropriate). It is essentially a compiler directive to tread carefully when optimising.
It indicates that an agent of which the compiler is not aware can change the value unexpectedly. (which could include other threads). First of all, one can not really rely on this for synchronisation, (One does not know when the monitor thread is interrupted, and the Other thread changes the value.) Furthermore it is quite inefficient as a synchronisation method. It typically means burning CPU Cycles waiting for something to happen. The better way is to put the thread to sleep, by the use of something like WaitForSingleObject(). That means that the CPU Cycles, in stead of being burned, can be used to speed up the printing of that 40 page report in Excell that is churning in the background. By using other synchronisation objects, such as CriticalSections, Mutexes and Semaphores (I prefer the SDK Versions, as the MFC versions are really Crap in MFC42), you can Manage and Control access to sections of code and GLOBAL and STATIC variables
Note that the Stack is thread safe, as in Windows, every thread has it's own private stack. Globals and Static Data however is stored on the same heap to which is available to all threads, however, not so easily by hardware threads, but that's a (very long) story for another day
Well, I'm 99.9% Sure that the use of 'volatile' is not at issue here, but I will certainly keep your much valued comment in mind
Kind Regards
N.B.
I Like your Signature
Bram van Kampen
|
|
|
|
|
You said
"Furthermore it is quite inefficient as a synchronisation method. It typically means burning CPU Cycles waiting for something to happen. The better way is to put the thread to sleep, by the use of something like WaitForSingleObject()."
First the method is not necessarily inefficient (it can be a lot faster than alternatives) and you can not use WaitForSingleObject to solve the problem in any way because the problem is you don't know when the change will occur. WaitForSingleObject hangs around and waits when you know a CHANGE OF SOMETHING MUST OCCUR. That function is of no use for the sort of problem you are dealing with it is used more for asynchronous transfers. The next part is correct.
Sychronization is the issue and CriticalSections, Mutexes and Semaphores are the only real way to get around it but THEY CAN BE EXTREMELY INEFFICIENT. A well used volatile with careful coding around the variable can save lots of messing around with synchronization in the simplest situations which is often 90% of cases. It is however NO GUARANTEED FIX you still have to understand what your threads are doing with memory access, the when where and how factors.
This statement by you => "All worked to perfection when I built a Skeleton Application, of essentially blank Dialogs.
Started to fill in Details, Controls, etc, and the App Clock Ticks are no longer recognised."
That tends to suggest you have a synchronization issue because your message posts are going AWL. The app clock tick should be picked up and delivered by DispatchMessage and it can't get lost unless something is going wrong with the memory .... It is delivered to a window based on handle. I would start with following the code for that tick message because it should be dead easy to put a watch on and see where it is getting dispatched to and why it is failing.
In vino veritas
|
|
|
|
|
I am trying to build an MFC application the uses a form with two panes, one for controls and the other for an OpenGL graphics window. I followed 2 code project for this task.
1. 15338/SDI-with-split-window by kencocomputers
2. Setting up OpenGL in an MFC control from codeguru C10975
The split window application part worked fine but I cannot initialize the openGL context in the graphics pane.
The classes in the project are:
1. CAboutDlg
2. CFormLeft
3. CFormRight
4. CMainForm
5. CMFC_SurfaceViwerApp
6. COpenGLControl
CFormLeft and CFormRight views are created in the CManFrame function
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
Specifically with:
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CFormLeft), CSize(300, 100), pContext) ||
!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CFormRight), CSize(100, 100), pContext))
{
m_wndSplitter.DestroyWindow();
return FALSE;
}
My question is how to actually implement the OpenGL Window; I suspect that it requires some code like:
void COpenGLControl::oglInitialize()
{
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,
0, 0, 0, 0, 0, 0, 0,
};
hdc = GetDC()->m_hDC;
m_nPixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, m_nPixelFormat, &pfd);
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
OnDraw(NULL);
}
But how does it activate? I put a call inside the oglCreate() function but nothing happened.
void COpenGLControl::oglCreate(CRect rect, CWnd *parent)
{
CString className = AfxRegisterWndClass(CS_HREDRAW |
CS_VREDRAW | CS_OWNDC, NULL,
(HBRUSH)GetStockObject(BLACK_BRUSH), NULL);
CreateEx(0, className, L"OpenGL", WS_CHILD | WS_VISIBLE |
WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rect, parent, 0);
m_oldWindow = rect;
m_originalRect = rect;
hWnd = parent;
oglInitialize();
}
I would appreciate any help I can get. Thanks
John H. Chumley
|
|
|
|
|
Since all this code is based on CodeProject articles you may get more help by using the forum at the end of the article. Also, you should not call OnDraw() directly, you should use the standard Windows rules for updating Windows. See UpdateWindow function (Windows)[^].
|
|
|
|
|
I have a existing function to communicate between Java and c++Activex I am using DISP_FUNCTION_ID. I need to add a default argument to the function so that I can call it from Java script. Is is possible to do so ?
Not sure how to add a default argument in the function which is accessed by using DISP_FUNCTION_ID. Need some assitance.
Thanks in advance.
|
|
|
|
|
Well,
I Know very little about Java, and this is an MFC/CPP Forum. In CPP a default argument is declared in the function declaration in a class, as in
class CMyClass{ int MyFunct(int Arg=0);};
This is a Declaration that MyClass has a Method named'MyFunct', which returns an int, and Optionally takes a Parameter (Arg),
and, that when I call this function without a parameter, that 0 will be assumed. You make those declarations in a 'Header File'
You Implement the function in the Implementation File,(Typically a CPP File) were you actually Implement the function:
int MyClass::MyFunct(int Arg)
if(Arg==0)return 1;
else return 2;
}
The above means that when using the class, you write:
MyClass myclass;myclass.MyFunct();myclass.MyFunct(0);myclass.MyFunct(12);
Your Marshalling Software beteween Java and CPP should give more details.
Bram van Kampen
|
|
|
|
|
Hi,
I have a console application that spawns a childprocess
I am initially able to get the MainFrame Window in the console app thru EnumThreadWindows
Later I create a modeless Dialog in the childprocess for which I would like the to get the HWND handle
I am running this code (both apps) under the Visual Studio debugger
So I can see when the child process creates the modeless dialogbox
I then step thru (under VS debugger) both GetWindow(MainFrame,GW_CHILD) and EnumChildWindows
and neither API return anything
|
|
|
|
|
What on Earth are you trying to Achieve!
Writing a Console Program trying to spawn an MFC Wnd App is not really possible, or desirable!
The only practical way this is possible is by the Console Program calling the Standard 'C' 'system(...)' function to launch the Windows App.
If you are looking for tooling to restart a misbehaving Windows Program, you came to the right door. I have just that.
The actual code is proprietary, but I can explain how it works.
Regards,
Bram.
Bram van Kampen
|
|
|
|
|
First of I apologize maybe I should spent more time looking up critical section
As all it is thread synchronization
I am a MainFrame assembler programmer by trade and was trying to learn new technology
I picked windows I wrote a front end for this C console program originally the code
was C then I re-wrote it in MFC C++ I am sure a more experienced C++ programmer could
have done a better job. But this was my way of learning
I created the Windows MFC C++ program with CreateProcess
|
|
|
|
|
ForNow wrote: I ended up having the debugging modeless dialog box HWND being returned to me from the SendMessage to the main window as both LRESULT and HWND are both 64 bits wide running 64 bit mode as I don't want the console program to sit around and wait for a response (and hold it up) I do a PostMessage from the console program
Thanks I (like Bram) am confused as to what you are trying to do here. Or indeed what your point is of using a console application to launch a Windows application, to launch a modeless dialog.
|
|
|
|
|
Without sight of your code it is anyone's guess what you are doing wrong.
|
|
|
|
|
I have three suggestion/comments:
1.) You said quote: "Later I create a modeless Dialog in the childprocess for which I would like the to get the HWND handle."
Doesn't matter which create method you use you get the handle back right then ... so why don't you hold it??????
2.) Like others I wonder why you are using MFC at all which will be problematic why would you not just use the WIN32 API.
3.) If GetWindow(MainFrame,GW_CHILD) and EnumChildWindows are returning false the your created window isn't parented
to the window at all. It's most likely parented to the desktop and again go back to number 1 above show us the how
you created the modeless dialog and check you gave it a parent.
The key point here is a show use the lines of code around the modeless dialog creation call.
In vino veritas
|
|
|
|
|
I did use GetWindow and got NULL. I was able to get Window Handle by doing a SendMessage to the other app as the return Value is From the other Window App (not Windows like PostMessage) I returned the dialog window in LRESULT
Thanks
|
|
|
|
|