It's 3.94 as I was working on something older, but it still may provide some useful insight into mutexes. Now let's hope *I* got it right in the first place
; purebasic survival guide - pb3.94
; mutex_1.pb - 05.06.2007 ejn (blueznl)
; http://www.xs4all.nl/~bluez/datatalk/purebasic.htm
;
; - creation and removal of mutexes
; - CreateMutex_()
; - CloseHandle_()
;
; note: purebasic 4's CreateMutex() command has not the same functionality as the Windows API CreateMutex_() !
;
#MUTEX_ALL_ACCESS = $1F0001
#WAIT_TIMEOUT = $102
#WAIT_ABANDONED = $80
#WAIT_FAILED = $FFFFFFFF
#WAIT_OBJECT_0 = $0
;
; *** opening and closing a mutex
;
; mutexes are unique single objects that can be 'owned' by applications, they are exclusive and can never be owned
; by two different owners at the same time, thus 'mutually exclusive' or 'mutex'
;
; a return value of 0 means something when wrong with the creation of the mutex
;
mutex_name.s = "test"
;
mutex_h = CreateMutex_(0,0,@mutex_name)
If mutex_h = 0
lasterror = GetLastError_()
Debug "not created"
EndIf
;
; a mutex will be destroyed if nobody owns it, and 1. the creator exits, or 2. a closehandle closes it
; as usual the best way is to properly close a mutex if you no longer use it :-)
;
; one way to check for the existence of a mutex is opening it, in which case it returns a handle to the mutex
; if the mutex didn't exist (yet) or was destroyed via CloseHandle_() this will return 0
;
mutex2_h = OpenMutex_(#MUTEX_ALL_ACCESS,0,@mutex_name)
If mutex2_h = 0
Debug "could not open"
Else
CloseHandle_(mutex2_h)
EndIf
;
; trying to create a mutex that already existed will result in creating a copy of the specified mutex
; GetLastError_() provides information on the creation of the mutex, and if it already existed
;
; (this mechanism can be used to create 'single instance' software, where a new instance will exit as it already
; detects another version of itself in memory, by trying to create such a mutex and exiting when it already
; existed)
;
mutex3_h = CreateMutex_(0,0,@mutex_name)
lasterror = GetLastError_()
If lasterror = #ERROR_ALREADY_EXISTS
Debug "already exists"
CloseHandle_(mutex3_h)
EndIf
;
; although windows seems to clean up abandoned mutexes, it's better to clean them up properly
;
CloseHandle_(mutex_h)
;
;
;
; *** mutex ownership
;
; only one instance (program) can 'own' a mutex, ownership can be established upon creation
; (the second parameter when set to '#True' makes the creator an owner)
; other threads / instances would open the existing mutex using OpenMutex_()
;
; mutex4_h = OpenMutex_(#MUTEX_ALL_ACCESS,0,@mutex_name)
;
mutex4_h = CreateMutex_(0,#True,@mutex_name)
;
; this program (the current instance, the code you're reading :-)) can try to get ownership of the mutex
; by calling WaitForSingleObject_() with a proper handle and a timeout parameter
;
; WaitForSingleObject_() will wait the specified nr. of milliseconds before continuing
;
result = WaitForSingleObject_(mutex4_h,50)
Select result
Case #WAIT_FAILED
Debug "failed"
Case #WAIT_ABANDONED
Debug "other process abandoned mutex"
Case #WAIT_TIMEOUT
Debug "other process still owns mutex"
Case #WAIT_OBJECT_0
Debug "success"
EndSelect
;
; 'abandoned' is a special case, it means the mutex was found but the previous owner is gone now, and you
; have now become the owner of the mutex
;
; if you no longer need to own a mutex, releasing is easy
;
ReleaseMutex_(mutex4_h)
;
; using WaitForSingleObject_() and ReleaseObject_() makes it possible to synchronize two applications with each
; other
;
; finally, when we're all done and about to exit the program we close the mutex
;
CloseHandle_(mutex4_h)
;
; a final note (thanks netmaestro!): it's worth noting at this point that despite their similar names,
; the CreateMutex_() API and purebasic 4's native CreateMutex() command are very differen: the CreateMutex()
; command deals with the management of critical section objects rather than mutex objects
;
Last edited by blueznl on Tue Jun 05, 2007 7:19 pm, edited 4 times in total.
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
mutex_name.s = "test"
mutex_h = CreateMutex_(0,0,@mutex_name)
If mutex_h=0
lasterror=GetLastError_()
Debug "not created":End
EndIf
; one way to check for the existence of a mutex is opening it, in which case it returns a handle to the mutex ?
mutex2_h=OpenMutex_(#MUTEX_ALL_ACCESS,0,@mutex_name)
If mutex2_h=0
Debug "could not open"
Else
If mutex_h=mutex2_h
Debug "Yeah! That's true: it returns the handle to the mutex"
Else
Debug "Noah! That's not true: it does not return the handle to the mutex"
EndIf
CloseHandle_(mutex2_h)
EndIf
CloseHandle_(mutex_h)
[...]
mutex_h = CreateMutex_(0,0,@mutex_name)
[...]
mutex2_h=OpenMutex_(#MUTEX_ALL_ACCESS,0,@mutex_name)
[...]
If mutex_h=mutex2_h
Debug "Yeah! That's true: it returns the handle to the mutex"
Else
Debug "Noah! That's not true: it does not return the handle to the mutex"
EndIf
[...]
Psychophanta, does not your code simply demonstrate that CreateMutex_() and OpenMutex_() return 2 separate values ?
Both functions produce valid, yet different, handles to the mutex.
Your test simply validates what was explained by Blueznl, no?
...or am I being dense here?
PB Forums : Proof positive that 2 heads (or more...) are better than one
blueznl wrote:Psycho, that's what I thought too, but appearently that is not the case. For example, many different objects can all be closed on the same way.
Looks like Windows API is not well done, surely because it is done by much different programmers with different philosophies
Psychophanta wrote:@Blue, ops! I believed every API object had a unique handle
Yeah, that's what I thought too, until I finally understood the meaning of "handle" (a numeric value, not necessarily unique, that allows access or reference to something)
Last edited by Blue on Sat Jul 05, 2008 7:34 pm, edited 1 time in total.
PB Forums : Proof positive that 2 heads (or more...) are better than one
Psychophanta wrote:[...]Looks like Windows API is not well done, surely because it is done by much different programmers with different philosophies
I don't know if I'd use "not well done" to describe the API, but it certainly has become a mess over time. Just look at the dizzying number of different pre-defined constants available for handles and types. It's enough to make you lose your latin! And most of them are uselessly redundant.
It would be nice if it were possible to clean the slate and redo the whole thing anew, with only 3 objectives in mind:
simplification, simplification, simplification.
Last edited by Blue on Sat Jul 05, 2008 7:41 pm, edited 1 time in total.
PB Forums : Proof positive that 2 heads (or more...) are better than one
blueznl wrote:ReleaseObject_() is wrong, that should be ReleaseMutex_().
OK, thanks.That's an important precision.
And now that you mention it, an obvious one at that !
(Don't forget to make the correction in your excellent tutorial.)
PB Forums : Proof positive that 2 heads (or more...) are better than one