Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Error #75 at Open {file} For Input As #1 (need 2 progs on same PC to communicate)
#11
(05-23-2024, 07:25 PM)Steffan-68 Wrote: I might have another thought.
I'm not particularly a fan of constantly writing to a file and deleting it again.
Since it looks like it's just a Windows program, how about writing stad to a file just using the clipboard?
It would all be in RAM and no HDD access.
Interesting idea... Maybe we can try that later. 
For now I have it working with DSMan195276's network code. 
(Will post soon in Works in Progress.)
Reply
#12
(05-23-2024, 06:56 PM)DSMan195276 Wrote:
(05-23-2024, 05:45 PM)Kernelpanic Wrote: One could almost compare it with a traffic light at an intersection: If North - South is green, then West - East has to wait (red) until it itself is green. If all road users stick to it, there won't be crashed.  Wink
Unfortunately Steve's approach can't prevent both programs from reading and writing at the same time, I don't think there's a way to do it with read/write file interactions alone.....

It can.  Tongue

Try these two programs out and watch them interact with a single file:

Code: (Select All)
Open "temp.txt" For Output As #1: Close 'make certain file is blank/new to begin with
Open "temp.txt" For Binary As #1

Do
    Select Case checkFile
        Case 11
            Print "Program 1 has control, is reading file."
            readfile
        Case 12
            Print "Program 1 has control, is writing to file."
            writefile
        Case 21
            Print "Program 2 has control, is reading file."
        Case 22
            Print "Program 2 has control, is writing to file."
        Case Else
            Print "File is free for usage."
            x = Int(Rnd * 100)
            Select Case x
                Case 10: writefile 'generate a random write every so often to see if we have issues
            End Select
    End Select
    _Limit 10
Loop

Sub readfile
    Dim temp As _Unsigned _Byte
    Dim junkdata As Long
    temp = 11
    Put #1, 1, temp
    _Delay .1 'wait 1/10 second to make certian other file isn't also trying to take control
    Get #1, 1, temp
    If temp <> 11 Then Exit Sub 'other file took control first.  We had a race condition and avoided it.
    Print "Recieved Data:"
    Do Until EOF(1)
        Get #1, , junkdata
        Print junkdata; ",";
    Loop
    Print
    'finished reading, free up the file now
    temp = 0
    Put #1, 1, temp
End Sub

Sub writefile
    Dim temp As _Unsigned _Byte
    Dim junkdata As Long
    temp = 12
    Put #1, 1, temp
    _Delay .1 'wait 1/10 second to make certian other file isn't also trying to take control
    Get #1, 1, temp
    If temp <> 12 Then Exit Sub 'other file took control first.  We had a race condition and avoided it.
    Print "Writing Data:"
    For i = 1 To 10
        junkdata = Int(Rnd * 100) + 1
        Put #1, , junkdata
        Print junkdata; ",";
    Next
    Print
    'finished reading, free up the file now
    temp = 21 'tell the second program that it's now time to read the file!
    Put #1, 1, temp
End Sub


Function checkFile~%%
    Dim temp As _Unsigned _Byte
    Get #1, 1, temp
    checkFile = temp
End Function

Code: (Select All)
Open "temp.txt" For Binary As #1

Do
    Select Case checkFile
        Case 21
            Print "Program 2 has control, is reading file."
            readfile
        Case 22
            Print "Program 2 has control, is writing to file."
            writefile
        Case 11
            Print "Program 1 has control, is reading file."
        Case 12
            Print "Program 1 has control, is writing to file."
        Case Else
            Print "File is free for usage."
            x = Int(Rnd * 100)
            Select Case x
                Case 10: writefile 'generate a random write every so often to see if we have issues
            End Select
    End Select
    _Limit 10
Loop

Sub readfile
    Dim temp As _Unsigned _Byte
    Dim junkdata As Long
    temp = 21
    Put #1, 1, temp
    _Delay .1 'wait 1/10 second to make certian other file isn't also trying to take control
    Get #1, 1, temp
    If temp <> 21 Then Exit Sub 'other file took control first.  We had a race condition and avoided it.
    Print "Recieved Data:"
    Do Until EOF(1)
        Get #1, , junkdata
        Print junkdata; ",";
    Loop
    Print
    'finished reading, free up the file now
    temp = 0
    Put #1, 1, temp
End Sub

Sub writefile
    Dim temp As _Unsigned _Byte
    Dim junkdata As Long
    temp = 22
    Put #1, 1, temp
    _Delay .1 'wait 1/10 second to make certian other file isn't also trying to take control
    Get #1, 1, temp
    If temp <> 22 Then Exit Sub 'other file took control first.  We had a race condition and avoided it.
    Print "Writing Data:"
    For i = 1 To 10
        junkdata = Int(Rnd * 100) + 1
        Put #1, , junkdata
        Print junkdata; ",";
    Next
    Print
    'finished reading, free up the file now
    temp = 11 'tell the second program that it's now time to read the file!
    Put #1, 1, temp
End Sub


Function checkFile~%%
    Dim temp As _Unsigned _Byte
    Get #1, 1, temp
    checkFile = temp
End Function

They set the flag for who has control, and skip doing anything unless they have control...  Then when they're finished writing, they set the flag so the other program now has control to read.   

Note that you can also use LOCK to make certain that only one program can access a file at a time, though I didn't mention it earlier as it's WINDOWS ONLY.  https://qb64phoenix.com/qb64wiki/index.php/LOCK
Reply
#13
This now reminds me of MySQL and PostgreSQL; that I once had to do with. The file that is currently being written to must of course be locked for other write access. . . otherwise there would be breakage.

This is all very complicated. And therefore very error-prone.
@madscijr, check the design of your program again.
Reply
#14
(05-23-2024, 08:30 PM)Kernelpanic Wrote: This now reminds me of MySQL and PostgreSQL; that I once had to do with. The file that is currently being written to must of course be locked for other write access. . . otherwise there would be breakage.

This is all very complicated. And therefore very error-prone.
@madscijr, check the design of your program again.
Yup, it was a terrible kludge! 
The latest version in WIP now uses DSMAN's network code, seems to be working better.
Reply
#15
(05-23-2024, 08:09 PM)SMcNeill Wrote: They set the flag for who has control, and skip doing anything unless they have control...  Then when they're finished writing, they set the flag so the other program now has control to read.   
I mean you didn't really solve the underlying problem, you simply avoided the race by adding a _Delay .1 Tongue

That said, one-way commutation with three states like you're doing has some potential. I'd still be concerned about caching, especially on Linux and Mac OS where we make use of the C++ file streams, but overall I think it's ok.
Reply
#16
(05-23-2024, 10:05 PM)DSMan195276 Wrote:
(05-23-2024, 08:09 PM)SMcNeill Wrote: They set the flag for who has control, and skip doing anything unless they have control...  Then when they're finished writing, they set the flag so the other program now has control to read.   
I mean you didn't really solve the underlying problem, you simply avoided the race by adding a _Delay .1 Tongue

That said, one-way commutation with three states like you're doing has some potential. I'd still be concerned about caching, especially on Linux and Mac OS where we make use of the C++ file streams, but overall I think it's ok.
If two programs could share the memory pointers for certain variables, that would be the fastest communication. Of course that opens up other problems, but if it was a bona-fide feature built into and managed by QB64PE, kind of like shared global variables - super global variables, ie shared across 2 or more processes, that might be kinda useful! I'm nowhere near as technical or knowledgable as the other folks here, so it's entirely possible it's not possible or a Bad Idea, but I figure it's worth asking about...
Reply
#17
(05-23-2024, 10:05 PM)DSMan195276 Wrote:
(05-23-2024, 08:09 PM)SMcNeill Wrote: They set the flag for who has control, and skip doing anything unless they have control...  Then when they're finished writing, they set the flag so the other program now has control to read.   
I mean you didn't really solve the underlying problem, you simply avoided the race by adding a _Delay .1 Tongue

That said, one-way commutation with three states like you're doing has some potential. I'd still be concerned about caching, especially on Linux and Mac OS where we make use of the C++ file streams, but overall I think it's ok.
You can skip that delay completely and the flag system will still work.  The programs just take turns working with the file.

Program 1 starts up.  Creates file.  Sets flag for "In use."  Writes to file.
Program 2 starts up.  File exists.  Checks flag.  It's in use... does nothing.
Program 1 finishes writing.  Sets flag for "Hey you, read this!"...  It now enters standby mode.
Program 2 sees flag.  Reads file..
Program 1...  File still flagged for program 2 use... wait...
Program 2 finishes reading file.   Now writes whatever data it needs to send back.
Program 1... File still flagged for program 2 use... wait....
Program 2 finishes writing to file.  Now sets flag to "Hey, Program 1, it's your turn!"
Program 1... Reads flag...  Takes control...

BINARY lets you read and write at the same time.  As long as the first byte in the file is set, you can toggle that back and forth to pass control to whichever program gets to use the file at any given time.  

May wear your drive out toggling that one byte over and over and over again, but it's quite doable. Smile

Even with caching, it wouldn't matter, as the control remains with the other program until that cache catches up and updates...  though if your cache doesn't push to file for a while, you may end up with both program just being locked in a waiting state until that write finally occurs.  Smile

And with that said, I still think the easiest way to do things would be to just OPEN "localhost" for TCP/IP and PUT/GET info back and forth like that between the two programs.  Smile
Reply
#18
(05-24-2024, 12:56 AM)SMcNeill Wrote:
(05-23-2024, 10:05 PM)DSMan195276 Wrote:
(05-23-2024, 08:09 PM)SMcNeill Wrote: They set the flag for who has control, and skip doing anything unless they have control...  Then when they're finished writing, they set the flag so the other program now has control to read.   
I mean you didn't really solve the underlying problem, you simply avoided the race by adding a _Delay .1 Tongue

That said, one-way commutation with three states like you're doing has some potential. I'd still be concerned about caching, especially on Linux and Mac OS where we make use of the C++ file streams, but overall I think it's ok.
You can skip that delay completely and the flag system will still work.  The programs just take turns working with the file.

Program 1 starts up.  Creates file.  Sets flag for "In use."  Writes to file.
Program 2 starts up.  File exists.  Checks flag.  It's in use... does nothing.
Program 1 finishes writing.  Sets flag for "Hey you, read this!"...  It now enters standby mode.
Program 2 sees flag.  Reads file..
Program 1...  File still flagged for program 2 use... wait...
Program 2 finishes reading file.   Now writes whatever data it needs to send back.
Program 1... File still flagged for program 2 use... wait....
Program 2 finishes writing to file.  Now sets flag to "Hey, Program 1, it's your turn!"
Program 1... Reads flag...  Takes control...

BINARY lets you read and write at the same time.  As long as the first byte in the file is set, you can toggle that back and forth to pass control to whichever program gets to use the file at any given time.  

May wear your drive out toggling that one byte over and over and over again, but it's quite doable. Smile

Even with caching, it wouldn't matter, as the control remains with the other program until that cache catches up and updates...  though if your cache doesn't push to file for a while, you may end up with both program just being locked in a waiting state until that write finally occurs.  Smile

And with that said, I still think the easiest way to do things would be to just OPEN "localhost" for TCP/IP and PUT/GET info back and forth like that between the two programs.  Smile

Yikes... That all seems a little too "bare metal" for comfort, lol. 
I'm sure it could work, the TCP/IP method just seems a lot cleaner, nice and simple! 

What about shared variables in memory? One program could use TCP/IP to pass a pointer to the address of the variable to the other EXE, and as long as both of them always write a fixed anount of bytes to it, they could swap values back and forth. It's also kind of low level, I'm just curious if it would perform any faster than pure TCP/IP...
Reply
#19
(05-24-2024, 12:56 AM)SMcNeill Wrote: You can skip that delay completely and the flag system will still work.  The programs just take turns working with the file.

Even with caching, it wouldn't matter, as the control remains with the other program until that cache catches up and updates...  though if your cache doesn't push to file for a while, you may end up with both program just being locked in a waiting state until that write finally occurs.  Smile
The issue is writefile, both programs call it when the status is zero. Imagine this flow:

Program 1 calls Checkfile, sees zero. Calls writefile
Program 2 calls checkFile, sees zero. Calls writefile
Program 2 calls Put #1 with 22
Program 2 calls Get #1, sees 22, continues
Program 1 calls Put #1 with 12
Program 1 calls Get #1, sees 12, continues

At this point, both programs have continued in writefile and are writing to the file at the same time. The delay effectively prevents this situation simply because the actual code in writefile takes less than .1 seconds to finish writing to the file. Even when both programs enter writefile, the delay means program 1 can't actually start writing until well after program 2 is done.

Caching can be a problem in the same situation, the program might not reread the status code from the file when you do the `Get`. In that situation the order doesn't matter, if they both call `writefile` then they both write to the file because they don't see eachother's status updates (and then like you said, get locked up as they won't see the status to read).
Reply




Users browsing this thread: 2 Guest(s)