Am Montag, 24. Juli 2006 23:38 schrieb Vinzent Höfler: > Vinzent Höfler wrote: > > Hmm. So we'd need a mutex inside a mutex. Now I know why they call > > it recursive. ;) So it'll be something like that: > > > > function Recursive_Mutex.Lock : ...; > > begin > > // Lock mutex inside mutex. > > self.Owner_Check_Lock.Lock; > > > > // Owned by current thread? > > if CurrentThreadId <> self.ThreadId then > > begin > > // Nope! Get the hell outta here. > > self.Owner_Check_Lock.Unlock; > > exit (NOT_OWNED); > > end {if}; > > > > // Now try locking the real mutex. > > if pthread_mutex_lock (self...) = 0 then > > begin > > self.Count := self.Count + 1; > > self.Owner_Check.Unlock; > > exit (SUCCESS); > > end {if}; > > > > self.Owner_Check.Unlock; > > exit (FAILURE); > > end {Mutex.Lock}; > > > > Something like that. Don't nail me on that, it's quite late and the > > heat is still killing me. ;) > > I knew it. Of course this is wrong. We can only lock the mutex once, > because we assume it's non-recursive, that was the whole point. So we > should *first* check the count and then may lock/unlock the mutex > accordingly.
* It's early, and I didn't dink enough coffee yet, so excuse me, if I overlook something ;-) some points: * In windows, I never used mutexes, as I didn't see the point. Usually, CriticalSections do what I want, except for IPC ... So I don't know if windows mutexes are recursive. However, IMO a CriticalSection should be recursive, so I stick to it here * pthread-Mutexes may not be used asynchronously (signal handlers are mentioned in the man page), so if we take that as basic rule, things get pretty simple: the same code is never executed simultanously from the same thread. * rtleventStartWait should have a counterpart rtlEventDoneWait, which unlocks the internal mutex of a rtlevent. * rtlWaitEvent should get a parameter telling it whether to call rtlEventDoneWait or not. (currently, it simply does it) * protect any method of a TCriticalSection with a internal critical section (a simple, non-recursive form should do the job) TCriticalSection.Enter; procedure internalEnter; begin OwnerThread:=GetCurrentThreadID; fLockCount:=1; ExternelLock.lock; end; begin internal.lock; if OwnerThread = 0 then begin //not locked yet internalEnter; end else begin //allready locked if OwnerThread=GetCurrentThreadID then //we are the owner inc(fLockCount) else begin //other thread owns the cs rtlEventStartWait(fExternalLock); internallock.unlock; rtlEventWaitFor(fExternalLock,DontAutoReleaseRTLEventMutex); internalLock.lock; rtlEventDoneWait(fExternalLock); internalEnter; end; end; internal.unlock; end; TCriticalSection.Leave; procedure internalEnter; begin OwnerThread:=GetCurrentThreadID; fLockCount:=1; ExternelLock.lock; end; begin internal.lock; try if OwnerThread <> GetCurrentThreadID then begin //we are not allowed //to leave, because we don't own it!not locked yet raise exception.create('leave on a foreign critical section'); end else begin //we are the owner if fLockCount = 0 then begin raise exception.create('leave on a unlocked section'); end else begin dec(fLockCount); if fLockCount=0 then rtlSetEvent(fExternalLock); end; end; finally internal.unlock; end; end; * just a quick draft. This one should be pretty much the same as a recursive mutex, i think .. * have to leave now, bbl. Maybe we meet in IRC later and/or setup a wiki page about this topic to collect and discuss proposals Regards, Burkhard _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal