Author Topic: Multiple Instances  (Read 29611 times)

grv575

  • Guest
Re: Multiple Instances
« Reply #15 on: September 11, 2005, 08:25:21 pm »
Using version 1.1, the
Environment->Settings->Run DDE Server
works as expected.

After checking this option, and restarting codeblocks, I can click on .cpp files and they open in codeblocks, and do not open a new instance but always use the same one.  If I click on the same file in explorer more than once, then a file is only opened once.  So no duplicate files problem when the DDE server is running.

Try Explorer->Tools->Folder Options->File Types
delete or change current .cpp file associations, then right-click on a .cpp file in explorer->open with...->codeblocks->always use this program.  Should work as above if it was an association problem.

Thomas: as an atomic operation I mean that for a set of instructions, all instructions finish as if they were one instruction, so that the scheduler cannot interrupt the running process and schedule another process which executes the same block of instructions concurrently (which would lead to problems like race conditions -- i.e. say one process issues a createtempfile operation followed by a event notification "I have created my tempfile" to 2nd process.  Now these two instructions are not atomic.  You can have p1: create tempfile, context switch p2: create tempfile, before any event notifications occur.  This can lead to difficult bugs - race conditions are nothing to shake a stick at.  And to get around this, of course you would put a lock(mutex) {} block around the two instructions (createtempfile, sendevent) to make them "atomic" w.r.t. other processes.  However, this relies on OS locking mechanisms and is in general non-portable.  wxWidgets wrappers must provide some cross-platform equivalents that do use the OS locking mechanisms specific to each platform, so would probably be ideal (haven't looked at them yet though)).

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Multiple Instances
« Reply #16 on: September 12, 2005, 01:35:52 am »
Using version 1.1, the
Environment->Settings->Run DDE Server
works as expected.
Hmm doesnt work for me on RC1-1 :(
Ah well... will have to live with it then.

Thomas: as an atomic operation I mean [...] scheduler cannot interrupt the running process [...]
i.e. say one process issues a createtempfile operation followed by a event notification "I have created my tempfile" to 2nd process.  Now these two instructions are not atomic.  You can have p1: create tempfile, context switch p2: create tempfile, before any event notifications occur.
Yes, I understand "atomic" :)
This is not really a problem, though. The case you describe is pretty much the same as case 3 in my above post. If you are really pedantic about what you execute and what you delete, and when, there are not so many bad things that can happen.
- When creating a tempfile, you can open it write-exclusive, this does not cost you anything. If the app crashes, you have one stale file lingering, but so what... after next reboot, it will be unlocked and can be deleted. As long as you have not closed your file, no one can delete it. So if another instance gets a notification from anywhere, and tries to delete that file, it will know that its contents is not valid.
- When getting a notification, you just look at everything you can get from that one directory.
If it is old, forget it and delete it. That way, no stale files persist forever.
Go on, read it in and try to delete the file. If the delete fails, forget it - it is still in use and you'll probably get another notification soon.
Otherwise, handle the contents that you have read in.

This is truly not atomic, but it is "atomic enough", that is, atomic where it absolutely must. When opening two files simultaneously, it does not matter in which order they are opened or how many milliseconds lie between opening them. Atomicity is only important here insofar as no requests should be completely lost, and no garbled data should be used. This is guaranteed by write-exclusive and delete. The good thing is it uses no OS-dependent features. The worst thing to happen is scanning a directory and opening one or two files in vain.
But well, given that the DDE server seems to work, this is purely academic now. Never change a working system. :)

EDIT: Little mistake of mine. You might rather append a char to the file before reading its contents. This is better because the read-delete strategy is in fact flawed. Appending a char to the file ensures that it has been closed by the other process (thus, its data is valid), and you can still read it in (minus one char) afterwards. This really makes it atomic. The delete can be any time later then.
« Last Edit: September 12, 2005, 01:42:38 am by thomas »
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

grv575

  • Guest
Re: Multiple Instances
« Reply #17 on: September 12, 2005, 02:13:01 am »
Hmm doesnt work for me on RC1-1 :(
Ah well... will have to live with it then.

Yeah I meant RC1-1.  For me whichever codeblocks was opened last (or a new one only if there are no CB's open) gets the files clicked in explorer.  I guess it obtaines the DDE server ownership.  I had .cpp files associated with dev-cpp but just changing the association to CB (so no special command strings for the file association) and enabling dde seemed to work.  Maybe clearing configuration settings as well?  I'm on WinXP.

Quote
EDIT: Little mistake of mine. You might rather append a char to the file before reading its contents. This is better because the read-delete strategy is in fact flawed. Appending a char to the file ensures that it has been closed by the other process (thus, its data is valid), and you can still read it in (minus one char) afterwards. This really makes it atomic. The delete can be any time later then.

See it's tricky  :)  I guess there is a way to do it right though (unix uses lock files after all which is similar)  If I did use some system like this for a project I think I'd write the smallest test app as a testbed and then run that through as many different conditions as possible to see that it behaved as expected (the previous sockets project I had to maintain was some guy's senior thesis which he just threw together and then ran off to microsoft... I guess I've grown skeptical of custom solutions (especially ones which don't come with lots of docs and unit test) rather than looking up on MSDN or whatever "how to do X").

zieQ

  • Guest
Re: Multiple Instances
« Reply #18 on: September 12, 2005, 09:08:38 am »
Just a little side note about lock files. This should be implemented as an option which would be set by default. I don't want to reboot Windows each time C::B will crash while debugging/implementing a new feature ;)

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Multiple Instances
« Reply #19 on: September 15, 2005, 07:28:12 pm »
And it gets better...

Today, I accidentially clicked on a .c file while Code::Blocks was running, and it worked just fine.

Funnily, it will work for .c, but not for any other file. To make sure it is not due to bad associations, I erased all source file associations using Explorer, this changed nothing. I then associated .xrc (previously unassigned) to Code::Blocks. It would open two instances, while .c would still reuse an existing one. Then I went to HKEY_CLASSES_ROOT, and checked the subkeys .c, .h, .cpp, and .cbp as well as their Codeblocks.* counterparts. They are precisely identical (except for the extension).
Next, I checked out HEAD and looked at the code that does the DDE handling. The function extracts the filename with a regex and calls MainFrame::Open it without ever looking at an extension.
How can it work for .c and not for .cpp? This is beyond me.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

grv575

  • Guest
Re: Multiple Instances
« Reply #20 on: September 15, 2005, 11:30:26 pm »
OK first try to clear out all references to file types.

delete HLCR\*.h,*.c,*.cpp
delete HKLM\software\classes\*.h,*.c,*.cpp
then delete all stuff in folder options->file types that remain

Click on a .cpp or .c in explorer and open with codeblocks, allow it to set itself as the default for these types (I got a messagebox asking).

Now the way the DDE server works is this:  *THE LAST* codeblocks that was opened (if you are using multiple CB instances) get registered as the DDE server.  So you have to be consistent.  Either always use windows explorer to open files in CB and don't start another instance if you plan on opening the same already open files using explorer.

See the problem is that you can open a couple cpp or c files.  It launches a CB instance.  Then you launch another CB instance, working on something else.  Now this new instance get the DDE server and if you try to open again files that are open in the first instance using windows explorer, then they will open in the second instance as well (since it now has the DDE server).

A fix for this behavior, hopefully giving better results, would be to change the single instance code.  1) always use a mutex to check for existing running CB instances (even if they unchecked the checkbox to disable multiple instances).  2) If the user allows multiple instances in the settings, then allow another CB to start _BUT_ do not startup the DDE plugin again.  Let the first CB instance always get be in charge of opening files from explorer.  Then you won't run into the problems above.

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Multiple Instances
« Reply #21 on: September 16, 2005, 04:10:35 pm »
delete HLCR\*.h,*.c,*.cpp
delete HKLM\software\classes\*.h,*.c,*.cpp
then delete all stuff in folder options->file types that remain

Click on a .cpp or .c in explorer and open with codeblocks, allow it to set itself as the default for these types (I got a messagebox asking).
Did all that with the same result again.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Multiple Instances
« Reply #22 on: September 16, 2005, 09:23:53 pm »
What about using ptypes (http://www.melikyan.com/ptypes/index.html)?

It is zblib licensed and offers cross-platform named pipes: http://www.melikyan.com/ptypes/doc/streams.namedpipe.html

A named pipe should work just fine, and it needs no obscure server processes. :)
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."