Burkhard Carstens wrote:
Am Montag, 24. Juli 2006 22:05 schrieb Vinzent Höfler:
Burkhard Carstens wrote:
Am Montag, 24. Juli 2006 20:33 schrieb Vinzent Höfler:
Burkhard Carstens wrote:
[..]

btw. this is not TEvent, we are talking about, it's rtlevent ..
TEvent (in synconjs) is implemented differently, and should work
like delphi/ windows TEvent, except that it is not capable of
timedwait ..
Well, if I'm looking at it correctly that's only because its
implementation is based on the POSIX semaphore. It could be using the
phtread_mutex stuff instead. The pthread-primitives are used anyway,
so I don't see problems with dependencies on  libpthread/libc or
so...

My idea was to use a rtlevent additionally and only when waitfor is called with timeout AND event is not signalled yet.

Why additionally? Do I miss something here? If done the proper way, everything in SyncObjs should be based on the basic RTL stuff. This would make the SyncObjs unit system independent with clearly defined semantics on all targets.

Of course, the original implementation (I suppose it came from Delphi?) was very windows-centric and made use of the available Windows-primitives directly. So maybe for Win32 it should even be kept this way, if not for anything else, somebody may say, for performance reasons at least.

Hmm, *looking closer* ... are there any differences between
Darwin/BSD/Linux/Solaris code at all? AFAICS, all these
implementations could be merged into a single one for Unix/POSIX
targets.

Don't know, maybe. However, we use PTHREAD_MUTEX_RECURSIVE_NP, where NP stands for NotPortable.. don't know which platforms support it and which not.

Well, those flags are somhow there, but there marked "XSI" in the OpenGroup's current specification, so probably most of our targets implement it - but it's still an extension.

That's why I voted for implementing most of the functionality in pascal and use pthread primitives only in their basic (i.e. mutex in non-recursive) form.

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. ;)

Well, a simple spinlock would even be better here for performance reasons, because first the locking time should be quite small, and second usually this code will be called in a sequential manner from within the same thread anyway. This would make the lock always being in an unlocked state under all sane circumstances.

Maybe even some overflow check in case someone tries to lock the mutex more than 2**32 times in a row? ;)

Same for unlock etc.


Vinzent.

_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to