|
Post by Rod on Dec 18, 2020 8:31:25 GMT -5
I have been playing a little. I was surprised to find that I can share a file between programs using "binary" file operations. The caveat is that the file access seems to need to be timed, don't know why, it just all freezes without the timer. But I can open files for read and write and they can all read the updates. The second caveat is that you must open and close the file. If you don't updates are not seen. Presumably this is Windows in the background caching the file read writes, closing the file forces the update.
This works on a simple three byte data file. Sub1 writes to the first textbox, the main program to the middle textbox and Sub2 writes to the third textbox. They all share the updated info.
Small multiuser database type application seems possible.
Run main first time in as it creates the data file, after that it does not matter what order they start in.
open "data.dat" for output as #dat #dat chr$(255);chr$(255);chr$(255); close #dat
nomainwin
textbox #1.t1, 20, 40, 60, 25 textbox #1.t2, 20, 70, 60, 25 textbox #1.t3, 20, 100, 60,25 WindowWidth = 300 : WindowHeight = 300 open "Multi User Test" for window as #1 #1 "trapclose [quit]"
timer 16,[write] wait
[write] open "data.dat" for binary as #dat seek #dat,0 a=asc(input$(#dat,1)) b=int(rnd(0)*255) #dat chr$(b); c=asc(input$(#dat,1)) close #dat #1.t1 a #1.t2 b #1.t3 c wait
[quit] timer 0 close #1 end
nomainwin textbox #1.t1, 20, 40, 60, 25 textbox #1.t2, 20, 70, 60, 25 textbox #1.t3, 20, 100, 60,25 WindowWidth = 300 : WindowHeight = 300 open "Sub1" for window as #1 #1 "trapclose [quit]"
timer 16,[read] wait
[read] open "data.dat" for binary as #dat seek #dat,0 a=int(rnd(0)*255) #dat chr$(a); b=asc(input$(#dat,1)) c=asc(input$(#dat,1)) close #dat #1.t1 a #1.t2 b #1.t3 c wait
[quit] timer 0 close #1 end
nomainwin textbox #1.t1, 20, 40, 60, 25 textbox #1.t2, 20, 70, 60, 25 textbox #1.t3, 20, 100, 60,25 WindowWidth = 300 : WindowHeight = 300 open "Sub2" for window as #1 #1 "trapclose [quit]"
timer 16,[read] wait
[read] open "data.dat" for binary as #dat seek #dat,0 a=asc(input$(#dat,1)) b=asc(input$(#dat,1)) c=int(rnd(0)*255) #dat chr$(c); close #dat #1.t1 a #1.t2 b #1.t3 c wait
[quit] timer 0 close #1 end
|
|
|
Post by pierre on Dec 19, 2020 14:57:36 GMT -5
Thank you, Rod, for this interesting example. I have also played a while with it. Actually, that took more than just a while, for my brain does not work at full speed anymore...
My findings are perhaps completely redundant compared to all you have already explained, but I always need a systematic approach to get a better understanding. If it is completely useless, you may disregard this post.
I launched the 3 instances of your program and saw them working. At first sight, this gives the impression of three users working simultaneously on the same file. But is this really true ?
In order to fully understand how it works, I separated the code into two operations 'Read' & 'Read/Write' and placed the 'timer 0' instruction just before the close #dat. I also added a couple of buttons that allow us to make one change at a time and see what happens.
You already mentioned the fact that a write operation is only visible for other users when the file is closed and reopened. That makes sens, so a writer has to close the file after finishing his update and that is exactly what you do.
But a reader also has to close and reopen the file before being able to see the changes.... That is what you are doing after all, for you have only one single combined 'Read/Write' operation.
We can see that the 3 instances can have the file open at the same time. The first time they launch a read operation, they obtain a view of the file, which is their personal view. In the beginning it is the same for all. Then, if a user launches a read/write operation, the change is immediately visible in his personal view. Other users must realize a read operation in order to refresh their own view.
I found out that when we keep the file open for one of the users, without these intermediate 'closes' and 'reopens', other users cannot see the changes made by this particular user, and the user himself can only see the initial view, plus his own changes.
NB. In a 'real life' database e.g. SQLite, the different instances remain open and a user can refresh his view just by launching a new SELECT statement, without the obligation of disconnecting from the database and then reconnect.
So your example is not really 'multi-threaded', it rather shows a hugh number of extremely fast but SUCCESSIVE accesses of the data file, offering a good simulation of a working database.
I think that this should also be possible for random access files ?
'**** only the first time ******** 'open "data.dat" for output as #dat '#dat chr$(255);chr$(255);chr$(255); 'close #dat
nomainwin
textbox #1.t1, 20, 40, 60, 25 textbox #1.t2, 20, 70, 60, 25 textbox #1.t3, 20, 100, 60,25 button #1.btn1, "Read", [go1], UL, 150,150 button #1.btn2, "Read/Write", [go2], UL, 150,200 WindowWidth = 300 : WindowHeight = 300 open "Multi User Test" for window as #1 #1 "trapclose [quit]" wait
[go1] timer 16,[read] [read] open "data.dat" for binary as #dat seek #dat,0 a=asc(input$(#dat,1)) b=asc(input$(#dat,1)) c=asc(input$(#dat,1)) timer 0 close #dat #1.t1 a #1.t2 b #1.t3 c wait
[go2] timer 16,[write] [write] open "data.dat" for binary as #dat seek #dat,0 a=asc(input$(#dat,1)) b=int(rnd(0)*255) #dat chr$(b); c=asc(input$(#dat,1)) timer 0 close #dat #1.t1 a #1.t2 b #1.t3 c wait
[quit] close #1 end
nomainwin textbox #1.t1, 20, 40, 60, 25 textbox #1.t2, 20, 70, 60, 25 textbox #1.t3, 20, 100, 60,25 button #1.btn1, "Read", [go1], UL, 150,150 button #1.btn1, "Read/Write", [go2], UL, 150,200 WindowWidth = 300 : WindowHeight = 300 open "Sub1" for window as #1 #1 "trapclose [quit]" wait
[go1] timer 16[read] [read] open "data.dat" for binary as #dat seek #dat,0 a=asc(input$(#dat,1)) b=asc(input$(#dat,1)) c=asc(input$(#dat,1)) timer 0 close #dat #1.t1 a #1.t2 b #1.t3 c wait
[go2] timer 16,[write] [write] open "data.dat" for binary as #dat seek #dat,0 a=int(rnd(0)*255) #dat chr$(a); b=asc(input$(#dat,1)) c=asc(input$(#dat,1)) timer 0 close #dat #1.t1 a #1.t2 b #1.t3 c wait
[quit] close #1 end
nomainwin statictext #1.txt, "File remains open", 20,10,200,25 textbox #1.t1, 20, 40, 60, 25 textbox #1.t2, 20, 70, 60, 25 textbox #1.t3, 20, 100, 60,25 button #1.btn1, "Read", [go1], UL, 150,150 button #1.btn2, "Read/Write", [go2], UL, 150,200 WindowWidth = 300 : WindowHeight = 300 open "Sub2" for window as #1 #1 "trapclose [quit]" open "data.dat" for binary as #dat timer 16,[begin] [begin] wait
[go1] seek #dat,0 a=asc(input$(#dat,1)) b=asc(input$(#dat,1)) c=asc(input$(#dat,1)) timer 0 'close #dat #1.t1 a #1.t2 b #1.t3 c wait
[go2] seek #dat,0 a=asc(input$(#dat,1)) b=asc(input$(#dat,1)) c=int(rnd(0)*255) #dat chr$(c); timer 0 'close #dat #1.t1 a #1.t2 b #1.t3 c wait
[quit] close #1 close #dat end
|
|
|
Post by pierre on Dec 21, 2020 11:14:46 GMT -5
Rod,
Comparing my findings with your observation about Windows caching in the background the read-write operations, I have the following understanding:
- Every user reads from - or writes to - and sees only - his own memory cache.
- Only closing the data file (connection) forces its update.
- A reader has to reopen the file in order to refresh his view.
- A user who keeps the file (connection) open, keeps meandering in his own memory cache without any chance of updating.
I don't know how Windows exactly realizes this cache process... The 3 instances of your program seem to run together without any error. So my question was : is this really concurrency or are the file accesses , besides being very fast, only successive ?
Simultaneous read accesses do seem possible, but what if two write operations (at a millisecond level) end up clashing together ? Does Windows then automatically realize the file locking ?
|
|
|
Post by Rod on Dec 21, 2020 12:09:12 GMT -5
I need to experiment more. I was surprised it ran at all. We could put error trapping for file not available. However my current worry is that if the file is held open the cache will simply overwrite other edits and set the file back to what it was.
However that said if Windows is queuing access requests and we rigorously open and immediately close then it may never happen.
Needs more experimentation when I get some time.
|
|
|
Post by pierre on Dec 21, 2020 12:18:44 GMT -5
Thanks, Rod. Interesting problem, indeed !
pierre
|
|