Actually, I found a way to simulate the single user access for reading and writing through a made up hacky lock type. The following would describe how I achieved it.
So, I made a small table in access, say, called Lock
, and has one column called SomeValue
. This column must be a primary key, and it could be of any value, so I made it of type number, for instance. This table will store all the locks that will be made in it, and the sides that are trying to acquire the lock must agree on the value of the lock. For instance, two clients will try to acquire lock of value 1, so they should request for lock 1, and release lock 1.
First, here are two helper queries I made to set and release the lock, by passing the value of the lock the sides that try to acquire it:
SetLock query:
INSERT INTO Lock (SomeValue)
VALUES ([GetLockValue]);
ReleaseLock query:
DELETE *
FROM Lock
WHERE SomeValue=[GetLockValue];
Then, here is the TrySetLock Function (which would try to set the lock of the passed in value, and return the set results, where 1 is a pass, and 0 is a fail) and SetLock Sub (which will wait until the lock by the passed in value is empty to acquire it - it uses spin lock method for lock acquiring):
Public Function TrySetLock(LockValue As Integer) As Integer
Dim dbs As dao.Database
Dim qdf As dao.QueryDef
Set dbs = CurrentDb
Set qdf = dbs.QueryDefs("SetLock")
qdf.Parameters("GetLockValue").Value = LockValue
qdf.Execute
TrySetLock = qdf.RecordsAffected
End Function
Public Sub SetLock(LockValue As Integer)
Do While TrySetLock(LockValue) = 0
Loop
End Sub
And here is the ReleaseLock Sub (which would release the lock by the passed in value - this Sub will always succeed, even if there no such lock exists):
Public Sub ReleaseLock(LockValue As Integer)
Dim dbs As dao.Database
Dim qdf As dao.QueryDef
Set dbs = CurrentDb
Set qdf = dbs.QueryDefs("ReleaseLock")
qdf.Parameters("GetLockValue").Value = LockValue
qdf.Execute
End Sub
As you may see here, I have used the help of the primary key property of SQL and Microsoft Access tables to make sure insertion (or as referred to here by locking) can only succeed for one side or client at a time, and will never succeed for the other side unless the first side removes (or releases) the lock of the same value of the lock both sides agree on.
However, this would pose a problem of blocking ALL clients relying on a same lock if one client failed to release the lock (say a client's program is frozen, and had to force kill the program). I would like to know if destructors for Class modules will be called when a program is forced to be killed or not? If it gets called, then I think this problem can be fixed by making a lock class with some value, and the destuctor of that class would release the lock, and not having to make other clients wait for that certain lock.