123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- /*=============================================================================|
- | PROJECT SNAP7 1.3.0 |
- |==============================================================================|
- | Copyright (C) 2013, 2015 Davide Nardella |
- | All rights reserved. |
- |==============================================================================|
- | SNAP7 is free software: you can redistribute it and/or modify |
- | it under the terms of the Lesser GNU General Public License as published by |
- | the Free Software Foundation, either version 3 of the License, or |
- | (at your option) any later version. |
- | |
- | It means that you can distribute your commercial software linked with |
- | SNAP7 without the requirement to distribute the source code of your |
- | application and without the requirement that your application be itself |
- | distributed under LGPL. |
- | |
- | SNAP7 is distributed in the hope that it will be useful, |
- | but WITHOUT ANY WARRANTY; without even the implied warranty of |
- | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
- | Lesser GNU General Public License for more details. |
- | |
- | You should have received a copy of the GNU General Public License and a |
- | copy of Lesser GNU General Public License along with Snap7. |
- | If not, see http://www.gnu.org/licenses/ |
- |==============================================================================|
- | |
- | Posix Threads support (Linux, FreeBSD) |
- | |
- |=============================================================================*/
- #ifndef unix_threads_h
- #define unix_threads_h
- //---------------------------------------------------------------------------
- #include "snap_platform.h"
- #include "snap_sysutils.h"
- #include <semaphore.h>
- #include <pthread.h>
- //---------------------------------------------------------------------------
- class TSnapCriticalSection
- {
- private:
- pthread_mutex_t mx;
- // int result;
- public:
- TSnapCriticalSection()
- {
- /*
-
- This would be the best code, but very often it causes a segmentation fault in many
- unix systems (the problem seems to be pthread_mutexattr_destroy()).
- So, to avoid problems in future kernel/libc release, we use the "safe" default.
-
- pthread_mutexattr_t mxAttr;
- pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&mx, &mxAttr);
- pthread_mutexattr_destroy(&mxAttr);
- */
- pthread_mutex_init(&mx, 0);
- };
- ~TSnapCriticalSection()
- {
- pthread_mutex_destroy(&mx);
- };
- void Enter()
- {
- pthread_mutex_lock(&mx);
- };
- void Leave()
- {
- pthread_mutex_unlock(&mx);
- };
- bool TryEnter()
- {
- return pthread_mutex_trylock(&mx) == 0;
- };
- };
- typedef TSnapCriticalSection *PSnapCriticalSection;
- //---------------------------------------------------------------------------
- const longword WAIT_OBJECT_0 = 0x00000000L;
- const longword WAIT_ABANDONED = 0x00000080L;
- const longword WAIT_TIMEOUT = 0x00000102L;
- const longword WAIT_FAILED = 0xFFFFFFFFL;
- class TSnapEvent
- {
- private:
- pthread_cond_t CVariable;
- pthread_mutex_t Mutex;
- bool AutoReset;
- bool State;
- public:
- TSnapEvent(bool ManualReset)
- {
- AutoReset = !ManualReset;
- if (pthread_cond_init(&CVariable, 0) == 0)
- pthread_mutex_init(&Mutex, 0);
- State = false;
- }
- ~TSnapEvent()
- {
- pthread_cond_destroy(&CVariable);
- pthread_mutex_destroy(&Mutex);
- };
- void Set()
- {
- pthread_mutex_lock(&Mutex);
- State = true;
- if (AutoReset)
- pthread_cond_signal(&CVariable);
- else
- pthread_cond_broadcast(&CVariable);
- pthread_mutex_unlock(&Mutex);
- };
- void Reset()
- {
- pthread_mutex_lock(&Mutex);
- State = false;
- pthread_mutex_unlock(&Mutex);
- }
- longword WaitForever()
- {
- pthread_mutex_lock(&Mutex);
- while (!State) // <-- to avoid spurious wakeups
- pthread_cond_wait(&CVariable, &Mutex);
- if (AutoReset)
- State = false;
- pthread_mutex_unlock(&Mutex);
- return WAIT_OBJECT_0;
- };
- longword WaitFor(int64_t Timeout)
- {
- longword Result = WAIT_OBJECT_0;
- if (Timeout == 0)
- Timeout = 1; // 0 is not allowed
- if (Timeout > 0)
- {
- pthread_mutex_lock(&Mutex);
- if (!State)
- {
- timespec ts;
- timeval tv;
- gettimeofday(&tv, NULL);
- uint64_t nsecs = ((uint64_t) tv.tv_sec) * 1000000000 +
- Timeout * 1000000 +
- ((uint64_t) tv.tv_usec) * 1000;
- ts.tv_sec = nsecs / 1000000000;
- ts.tv_nsec = (nsecs - ((uint64_t) ts.tv_sec) * 1000000000);
- do {
- Result = pthread_cond_timedwait(&CVariable, &Mutex, &ts);
- if (Result == ETIMEDOUT)
- Result = WAIT_TIMEOUT;
- } while (Result == 0 && !State);
- }
- else
- if (AutoReset) // take the ownership
- State = false;
- pthread_mutex_unlock(&Mutex);
- return Result;
- }
- else // Timeout<0
- return WaitForever();
- };
- };
- typedef TSnapEvent *PSnapEvent;
- //---------------------------------------------------------------------------
- class TSnapThread
- {
- private:
- pthread_t th;
- bool FCreateSuspended;
- void ThreadCreate();
- void ThreadJoin()
- {
- pthread_join(th, 0);
- };
- void ThreadKill()
- {
- pthread_cancel(th);
- };
- longword ThreadWait(uint64_t Timeout)
- {
- longword Elapsed = SysGetTick();
- while (!Closed && !(DeltaTime(Elapsed) > Timeout))
- SysSleep(100);
- if (Closed)
- return WAIT_OBJECT_0;
- else
- return WAIT_TIMEOUT;
- };
- protected:
- bool Started;
- public:
- bool Terminated;
- bool Closed;
- bool FreeOnTerminate;
- TSnapThread();
- virtual ~TSnapThread();
- virtual void Execute()
- {
- };
- void Start();
- void Terminate();
- void Kill();
- void Join();
- longword WaitFor(uint64_t Timeout);
- };
- typedef TSnapThread *PSnapThread;
- //---------------------------------------------------------------------------
- #endif // unix_threads_h
|