Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: MdsIpThreadStatic ConnectionList; should fix deadlock and be faster #2288

Merged
merged 174 commits into from
May 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
174 commits
Select commit Hold shift + click to select a range
423fac4
clang-format
zack-vii May 3, 2021
3658251
Fixed race conditions in ServerBuildDispatchTable
zack-vii Apr 24, 2021
2fdf93a
fix memory leaks in TclDispatch_show_server and in ServerMonitoCheckin
zack-vii Apr 24, 2021
d229e1b
removed tdicompile DEBUG
zack-vii Apr 21, 2021
389b377
MdsipThreadStatic
zack-vii Apr 22, 2021
8b6d4ed
SendMdsMsg send_bytes
zack-vii Apr 22, 2021
2821dd5
client_event_ast use GetConnectionClientType
zack-vii Apr 22, 2021
ad7bdc9
MdsIpGetDescriptor use GetConnectionVersion
zack-vii Apr 22, 2021
8bf66dc
use Invalid Connection in ConnectToMds
zack-vii Apr 22, 2021
abc12ac
ConnectionLock Sending to Requests
zack-vii Apr 22, 2021
926a136
eliminate cvtdef
zack-vii Apr 22, 2021
8cc32bb
DoMessage: status and close
zack-vii Apr 22, 2021
80c01e6
DoMessage is an Activity
zack-vii Apr 22, 2021
bc5da10
CloseConnection tdicontext
zack-vii Apr 22, 2021
675f2c4
GetMdsMsg.c as recv
zack-vii Apr 22, 2021
670c49e
ProcessMessage: debug send reply
zack-vii Apr 22, 2021
91fc24b
PopConnection
zack-vii Apr 22, 2021
7fd5bf3
threadstatic client addr
zack-vii Apr 22, 2021
1f30a1c
updated ioroutinesx
zack-vii Apr 22, 2021
61ba6ee
ioroutined tcp threaded
zack-vii Apr 22, 2021
d3fea55
python fixed Connection object
zack-vii Apr 22, 2021
0c5098b
Client used threaded connections
zack-vii Apr 22, 2021
6362bee
fixed race on connection_id thru local lock
zack-vii Apr 22, 2021
4df2e03
memory leak in pipes
zack-vii Apr 22, 2021
dc603a1
cleanup destroyConnection etc
zack-vii Apr 22, 2021
1971b46
cleanup thread static connections
zack-vii Apr 22, 2021
903095c
invalis message_id
zack-vii Apr 22, 2021
adaf97a
io dont destroy
zack-vii Apr 22, 2021
bad506c
io race
zack-vii Apr 22, 2021
a8a939c
atexit() and udt extracted refresh_list()
zack-vii Apr 22, 2021
9e51b43
race in AcceptConnection
zack-vii Apr 22, 2021
67dd9a3
windows io_pipes_t init
zack-vii Apr 22, 2021
a07b623
pop_client
zack-vii Apr 22, 2021
51bd5d5
try multithreaded udt
zack-vii Apr 22, 2021
76d46d1
fixed username in AcceptConnection
zack-vii Apr 22, 2021
3bb89d7
udt: better error message
zack-vii Apr 22, 2021
5f2ba3a
fixed cleanup,; ClientList->next
zack-vii Apr 22, 2021
40dadff
pipes fixed
zack-vii Apr 23, 2021
7182fe3
cleanup destroy
zack-vii Apr 23, 2021
8ce7d11
fixed memory leak in IoThread
zack-vii Apr 24, 2021
019cb36
revert kind of.. ProcessMessage returns with TRUE if message free is …
zack-vii Apr 24, 2021
eb30193
fixed cleanup in TdiGetData
zack-vii Apr 27, 2021
c9aed9e
fixed memory leak in servershr
zack-vii Apr 27, 2021
1d44199
added suppression for glibc getservbyname
zack-vii Apr 27, 2021
5052568
status: fixed RETURN_IF_STATUS_NOT_OK
zack-vii Apr 27, 2021
eb519c6
fixed memoryleak in TdiCall
zack-vii Apr 27, 2021
32f150c
replaced all DBG with mdsdbg.h
zack-vii Apr 28, 2021
1e12310
added potential debug messages and fixed servershr issue in ReplyThread
zack-vii Apr 28, 2021
c533dfa
python tests: can use external action monitor
zack-vii Apr 29, 2021
2e4dd7f
removed mdsdebug.c
zack-vii Apr 29, 2021
ee42a64
generically fixed (status & 1) and !(status & 1)
zack-vii Apr 29, 2021
c64dca4
fixed (!status & 1) in dwscope, xmdsshr, and hdf5
zack-vii Apr 29, 2021
b9091ea
added time to DBG
zack-vii Apr 29, 2021
43e68c0
added more potential debug messages
zack-vii Apr 29, 2021
5c500e8
cleanup do_callback_done and debug
zack-vii Apr 30, 2021
e6e9153
shortcut if connection id invalid
zack-vii Apr 30, 2021
6a8f33e
use JOB_PRI and CLIENT_PRI and fixed JobId
zack-vii Apr 30, 2021
ec8acc3
fixed Exception issues in a3248.py
zack-vii Apr 30, 2021
c886ed4
fixed mdslib status
zack-vii Apr 30, 2021
c37911b
fixed mdsip setup/cleanup in python tests
zack-vii Apr 30, 2021
be3c022
dont try to stop server; this may hang
zack-vii Apr 30, 2021
22642f7
cleanup DispatchPhase; disable ACTION_DONE_THREAD
zack-vii Apr 30, 2021
315d1df
make_idents fixup type
zack-vii Apr 30, 2021
2daa161
fixed mdsdbg if not DEBUG
zack-vii Apr 30, 2021
19e892a
moved private shared includes out of teh way
zack-vii May 2, 2021
9ee8e90
fixed ACTION_DBG
zack-vii May 2, 2021
d927cf6
socket_port includes socket error handling for windows
zack-vii May 2, 2021
9993b6f
deal with oses without MSG_NOSIGNAL
zack-vii May 2, 2021
87607e0
disconnect on destroy
zack-vii May 2, 2021
923a183
moved mit headers to mitdevices
zack-vii May 2, 2021
92a3731
fixed pointer issues in Xmds
zack-vii May 2, 2021
96c47aa
fixed misc pointer issues
zack-vii May 2, 2021
1c727dd
safe load_lib in librtl
zack-vii May 2, 2021
d5efc7f
replace with MUTEXT_LOCK_PUSH
zack-vii May 2, 2021
1a2e277
DEFINE_INITIALIZESOCKETS
zack-vii May 2, 2021
a76ca08
servershr: action_done lock
zack-vii May 2, 2021
1592493
include socket_port fiorst for windows winsock2 order
zack-vii May 2, 2021
d241f4c
servershr/ debug
zack-vii May 2, 2021
44a69ce
avoid static vars in javamds
zack-vii May 3, 2021
092f866
added MdsIpTest and fixed client side MdsIpGetDescriptor
zack-vii May 3, 2021
ddd59ef
fixed mdsip SerialIO
zack-vii May 3, 2021
48a6978
fixed alpine and disable debug
zack-vii May 3, 2021
22fbc31
addresses issues popped by macosx
zack-vii May 4, 2021
08aed92
suppress python leaks and make race condition of STATIC_debug values …
zack-vii May 3, 2021
22c5e89
suppress helgrind misc in dlopen
zack-vii May 4, 2021
949781d
handle clobbered in LibFreeVm
zack-vii May 4, 2021
a6829b1
wait for mdsip server in _start_mdsip
zack-vii May 4, 2021
185e98c
user tcpv6 as default protocol
zack-vii May 5, 2021
eadcbbe
Windows socket error use FormatMessageW to get propert message
zack-vii May 4, 2021
d05fc19
mdstcpip: make tracks changes in io_routines headers
zack-vii May 5, 2021
747a9a8
move io_check to tcp header
zack-vii May 5, 2021
153816d
Tests: no need for pthread.h in mdsip and added mdsip tcp in tests
zack-vii May 5, 2021
37cfe7a
cleanup UdpEvent in mdsshr
zack-vii May 7, 2021
4c6947b
decouple socket_port and pthread_port headers
zack-vii May 7, 2021
9540282
mdsmsg.h and cpp thread helper to support both posix and windows
zack-vii May 7, 2021
c60d4b9
removed Threads from testutils as it could block under windows
zack-vii May 7, 2021
6717f51
Close ocket to signal cancel in ioreoutinesx.h
zack-vii May 7, 2021
a92c58c
avoid pthread_cancel for Win32 in MDSIpTest
May 7, 2021
8ba1130
fixe race in UdpEvent again
May 7, 2021
c164eba
mdstcpip tests-valgrind
zack-vii May 7, 2021
3369ee9
Windows cannot really do tcpv6
zack-vii May 8, 2021
29b20e3
fail with -1 on MdsConnect
zack-vii May 8, 2021
cfd8aa3
setting: mdsip timeout 10 sec not infty
zack-vii May 8, 2021
cf85e6c
fixed connect and listen
zack-vii May 8, 2021
7e69f15
TRY disconnect in thread
zack-vii May 9, 2021
0a5f769
use compression not maxcompression on windows service
zack-vii May 11, 2021
03d77b2
cleanup deprecated methods
zack-vii May 11, 2021
f2e384b
clang-format.sh
zack-vii May 11, 2021
5e957fe
STATIC_lock for STATIC
zack-vii May 12, 2021
c834498
missing newline
zack-vii May 12, 2021
d0a896a
suppress _PyObject_MakeTpCall holds lock on exit
zack-vii May 12, 2021
7a61c89
call it action
zack-vii May 12, 2021
9210fb8
activated some debug messages
zack-vii May 12, 2021
65c2504
accessible TestEnv
zack-vii May 12, 2021
4e067a6
Makefile servershr depend on servershrp.h
zack-vii May 12, 2021
58b9f0d
ServerShr debug
zack-vii May 12, 2021
2876aa3
use strdup
zack-vii May 13, 2021
1be10f9
include threadid in debug
zack-vii May 13, 2021
e1dec47
some cleanup in servershr
zack-vii May 13, 2021
7be47db
fixup python tests
zack-vii May 13, 2021
7f7a788
more verbosity if debug symbols are added
zack-vii May 13, 2021
a3d5b87
fixed PATH_DOWN issue on dispatch
zack-vii May 13, 2021
3d4ff40
suppress Server unknown message
zack-vii May 13, 2021
d2ad164
added python helgrind suppression
zack-vii May 13, 2021
1603a32
fixed race on free in ServerWait
zack-vii May 13, 2021
6ab00f5
fixed tditests against variables and different OS
zack-vii May 13, 2021
68a76cf
fixed memory leak in ShowServerInfo
zack-vii May 13, 2021
0eea820
fixed tdi tests
zack-vii May 13, 2021
c2c52ef
macosx does not do gettid or getpid
zack-vii May 13, 2021
5babf6f
clobbered in ServerConnect
zack-vii May 14, 2021
f66c608
cloberser in Client_remove
zack-vii May 14, 2021
1b1e32c
fixup abandon
May 14, 2021
6e07bbe
use mdsshr (private) LibGetHostAddr
zack-vii May 14, 2021
50843fc
clobbered err in Job_wait_and_pop_by_jobid
zack-vii May 14, 2021
21b9888
fixed _LibGetHostAddr signature and portstr
zack-vii May 14, 2021
5f52466
Windows become_user with words
May 14, 2021
612e168
fixed mdstcpip brought windows and linux closer
zack-vii May 14, 2021
84e4c3e
fixed mdsip more shared code betewwn windows and linux
May 14, 2021
bb8c240
clang and fixed remaining pthread_cancel
May 14, 2021
c8dfb6d
Windows dsc_dispatcher_test runs when started manually wine python -B…
May 14, 2021
db30fed
initialize lerror
May 15, 2021
60be800
use same executions in tditest
May 15, 2021
972837f
allow to change default mdsip protocoll but dont use tcpv6 as default
May 15, 2021
02ea664
alpine has a lower default thread stack size. set size to working value
May 15, 2021
f232f99
suppress message on connection close
May 15, 2021
b4426ce
fixed RemoteAccess to work with multithreaded segment remote writes
May 15, 2021
38586d5
activated and standadized connection_write_test
May 15, 2021
36c63cb
MDSSHR_LOAD_LIBROUTINE to load from other lib
zack-vii May 17, 2021
5f891d2
cleanup treeshr RemoteAccess
zack-vii May 17, 2021
1c352a3
Connection debug messages
zack-vii May 17, 2021
8a842c3
IoRoutinesTunnel: redirect stdout for windows
zack-vii May 17, 2021
814675e
clang python_test
zack-vii May 17, 2021
e776c0b
PIPES_OBJECTS depend on ioroutines_pipes.h
zack-vii May 17, 2021
6dc989b
mdsipshr/ConnectToMds.c
zack-vii May 17, 2021
de93018
io_routines/IoRoutinesTunnel.c
zack-vii May 17, 2021
8498bd4
cleanup Connections, set flag if in list
zack-vii May 17, 2021
4cb51bf
use fixup_eventname
zack-vii May 18, 2021
bde31b1
mdsipshar depends on mdsip_connections.h
zack-vii May 18, 2021
4523437
CON_PRI and CON_VAR pair for messages
zack-vii May 18, 2021
925b4c5
HOST_PRI and HOST_VAR pair and fixed leak
zack-vii May 18, 2021
27e2f58
fixed MdsEvent alloc_eventname
zack-vii May 18, 2021
730ac03
used strdup where possible
zack-vii May 18, 2021
279f7ea
tcl cleanup mdsdclAddCommands
zack-vii May 18, 2021
e5f5eb1
cleanup complexity of send_response
zack-vii May 18, 2021
bc779c6
connection_write_test.py causes valgrind to hang?
zack-vii May 18, 2021
69c2372
use mdsip_stop to clean up
zack-vii May 18, 2021
1437253
reenable SetMdsplusFileProtection suppression
zack-vii May 18, 2021
34559b1
added timeout to assertRun
zack-vii May 18, 2021
cbf61b4
debug strings in mdsipshr
zack-vii May 18, 2021
8c6b0df
eliminated confusing STATCIdef.h
zack-vii May 18, 2021
0d7fe14
use more advanced version for clock_gettime substitutes
zack-vii May 18, 2021
14fd90a
fixed deadlock if job finishes fast
zack-vii May 18, 2021
e5ee2d1
final clang-format
zack-vii May 18, 2021
ad94040
python.Connection, removed to local for a conn
zack-vii May 19, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ mdsshr/testing/Makefile.in
mdsshr/version.h
mdstcpip/docs/Makefile.in
mdstcpip/docs/img/Makefile.in
mdstcpip/testing/Makefile.in
mdstcpip/zlib/Makefile.in
python/MDSplus/docs/Makefile.in
python/MDSplus/compound.py
Expand Down
2 changes: 1 addition & 1 deletion Makefile.inc.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
echo-%: --always
@echo '$* = $($*)'

DEFAULT_CFLAGS=-g -O3
DEFAULT_CFLAGS = -O3

ifeq "$(NOWARN)" ""
WARNFLAGS = @WARNFLAGS@
Expand Down
282 changes: 282 additions & 0 deletions _include/P2WMutex.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
#pragma once
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#define __STDC_FORMAT_MACROS

#include <string.h>

#include <atomic>
#include <chrono>
#include <stdexcept>
#include <mutex>
#include <condition_variable>

#ifdef _P2W_GTHREADS
#include <windows.h>
#include <synchapi.h>
#include <processthreadsapi.h>
#endif

#include "mdsmsg.h"

#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

#undef P2W_PTHREAD_CLEANUP
#ifdef P2W_PTHREAD_CLEANUP
template <class _Lock>
static void p2w_cleanup_lock(void *arg) { ((_Lock *)arg)->unlock(); }
#define P2W_LOCK_CLEANUP_PUSH(lock) pthread_cleanup_push(p2w_cleanup_lock<decltype(lock)>, (void *)&lock)
#define P2W_LOCK_CLEANUP_POP(lock) pthread_cleanup_pop(0)
#else
#define P2W_LOCK_CLEANUP_PUSH(lock)
#define P2W_LOCK_CLEANUP_POP(lock)
#endif
#define P2W_UNIQUE_LOCK_ACQUIRE(lock, mutex) \
{ \
std::unique_lock<const decltype(mutex)> lock(mutex); \
P2W_LOCK_CLEANUP_PUSH(lock)
#define P2W_UNIQUE_LOCK_ADOPT(lock, mutex) \
{ \
std::unique_lock<const decltype(mutex)> lock(mutex, std::adopt_lock); \
P2W_LOCK_CLEANUP_PUSH(lock)
#define P2W_UNIQUE_LOCK_RELEASE(lock, mutex) \
P2W_LOCK_CLEANUP_POP(lock); \
}
#define P2W_SHARED_LOCK_ACQUIRE(lock, mutex) \
{ \
(mutex).lock_shared(); \
std::unique_lock<const decltype(mutex)> lock(mutex, std::adopt_lock); \
P2W_LOCK_CLEANUP_PUSH(lock)
#define P2W_SHARED_LOCK_ADOPT(lock, mutex) \
{ \
std::unique_lock<const decltype(mutex)> lock(mutex, std::adopt_lock); \
P2W_LOCK_CLEANUP_PUSH(lock)
#define P2W_SHARED_LOCK_RELEASE(lock, mutex) \
P2W_LOCK_CLEANUP_POP(lock); \
}

template <class Duration>
static inline void p2w_time_point_to_timespec(const std::chrono::time_point<std::chrono::system_clock, Duration> &time_point, struct timespec &ts)
{
auto nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(time_point.time_since_epoch());
auto sec = std::chrono::duration_cast<std::chrono::seconds>(nsec);
nsec -= sec;
ts.tv_sec = sec.count();
ts.tv_nsec = nsec.count();
}

#define _P2W_PTHREAD // define st

#ifndef _P2W_PTHREAD
#define P2WMutex std::mutex
#else
#include <exception>

class P2WCond;
template <typename T, int (*TRYLOCK)(T *), int (*LOCK)(T *), int (*UNLOCK)(T *)>
class _P2WMutex
{
friend P2WCond;

protected:
T native;

public:
bool try_lock() const
{
bool const locked = TRYLOCK((T *)&native) == 0;
if (locked)
MDSDBG("MUTEX: 0x%" PRIxPTR " locked 0x%" PRIxPTR, (uintptr_t)pthread_self(), (uintptr_t)this);
return locked;
}
void lock() const
{
#ifdef DEBUG
if (try_lock())
return;
#endif
MDSDBG("MUTEX: 0x%" PRIxPTR " wait for 0x%" PRIxPTR, (uintptr_t)pthread_self(), (uintptr_t)this);
int const err = LOCK((T *)&native);
if (err != 0)
throw std::runtime_error(strerror(err));
MDSDBG("MUTEX: 0x%" PRIxPTR " locked 0x%" PRIxPTR, (uintptr_t)pthread_self(), (uintptr_t)this);
}
void unlock() const
{
MDSDBG("MUTEX: 0x%" PRIxPTR " unlocking 0x%" PRIxPTR, (uintptr_t)pthread_self(), (uintptr_t)this);
int const err = UNLOCK((T *)&native);
if (err != 0)
throw std::runtime_error(strerror(err));
}
T *native_handle() { return &native; };
};

class P2WMutex : public _P2WMutex<pthread_mutex_t, pthread_mutex_trylock, pthread_mutex_lock, pthread_mutex_unlock>
{
public:
P2WMutex(const pthread_mutexattr_t *attr = NULL)
{
int const err = pthread_mutex_init(&native, attr);
if (unlikely(err != 0))
throw std::runtime_error(strerror(err));
};
~P2WMutex()
{
pthread_mutex_destroy(&native);
}
P2WMutex(int const type)
{
pthread_mutexattr_t attr;
int err = pthread_mutexattr_init(&attr);
if (unlikely(err != 0))
throw std::runtime_error(strerror(err));
err = pthread_mutexattr_settype(&attr, type);
if (unlikely(err != 0))
throw std::runtime_error(strerror(err));
err = pthread_mutex_init(&native, &attr);
if (unlikely(err != 0))
throw std::runtime_error(strerror(err));
pthread_mutexattr_destroy(&attr);
}
};

class P2WSharedMutex : public _P2WMutex<pthread_rwlock_t, pthread_rwlock_trywrlock, pthread_rwlock_wrlock, pthread_rwlock_unlock>
{
public:
P2WSharedMutex(const pthread_rwlockattr_t *attr = NULL)
{
int const err = pthread_rwlock_init(&native, attr);
if (unlikely(err != 0))
throw std::runtime_error(strerror(err));
};
~P2WSharedMutex()
{
pthread_rwlock_destroy(&native);
}
bool try_lock_shared() const
{
bool const locked = pthread_rwlock_tryrdlock((pthread_rwlock_t *)&native) == 0;
if (locked)
MDSDBG("MUTEX: 0x%" PRIxPTR " rdlocked 0x%" PRIxPTR, (uintptr_t)pthread_self(), (uintptr_t)this);
return locked;
}
void lock_shared() const
{
#ifdef DEBUG
if (try_lock_shared())
return;
#endif
MDSDBG("MUTEX: 0x%" PRIxPTR " rdwait for 0x%" PRIxPTR, (uintptr_t)pthread_self(), (uintptr_t)this);
int const err = pthread_rwlock_rdlock((pthread_rwlock_t *)&native);
if (err != 0)
throw std::runtime_error(strerror(err));
MDSDBG("MUTEX: 0x%" PRIxPTR " rdlocked 0x%" PRIxPTR, (uintptr_t)pthread_self(), (uintptr_t)this);
}
void unlock_shared() const { unlock(); }
};

static_assert(sizeof(pthread_mutex_t) == sizeof(P2WMutex), "Size is not correct");
#endif

#ifndef _P2W_PTHREAD
class P2WCond : public std::condition_variable
{
public:
void wait(std::unique_lock<const P2WMutex> &lock)
{
while (std::cv_status::timeout == wait_until(
lock, std::chrono::time_point<std::chrono::system_clock>::max()))
;
}
template <class Predicate>
void wait(std::unique_lock<const P2WMutex> &lock, Predicate pred)
{
while (!wait_until(
lock, std::chrono::time_point<std::chrono::system_clock>::max(), pred))
;
}
};
#else
class P2WCond
{
public:
pthread_cond_t native;
P2WCond()
{
if (pthread_cond_init(&native, NULL) != 0)
throw std::runtime_error(strerror(errno));
}
~P2WCond()
{
pthread_cond_destroy(&native);
}
P2WCond(const P2WCond &) = delete;
P2WCond &operator=(const P2WCond &) = delete;
void notify_one() noexcept
{
pthread_cond_signal(&native);
}
void notify_all() noexcept
{
pthread_cond_broadcast(&native);
}
void wait(std::unique_lock<const P2WMutex> &lock)
{
const int err = pthread_cond_wait(&native, (pthread_mutex_t *)&lock.mutex()->native);
if (unlikely(err != 0))
throw std::runtime_error(strerror(err));
}
template <class Predicate>
void wait(std::unique_lock<const P2WMutex> &lock, Predicate pred)
{
while (!pred())
{
const int err = pthread_cond_wait(&native, (pthread_mutex_t *)&lock.mutex()->native);
if (unlikely(err != 0))
throw std::runtime_error(strerror(err));
}
}
template <class Duration>
std::cv_status wait_until(std::unique_lock<const P2WMutex> &lock, const std::chrono::time_point<std::chrono::system_clock, Duration> &abs_time)
{
struct timespec ts;
p2w_time_point_to_timespec(abs_time, ts);
const int err = pthread_cond_timedwait(&native, &lock.mutex()->native, &ts);
if (likely(err == 0))
return std::cv_status::no_timeout;
if (likely(err == ETIMEDOUT))
return std::cv_status::timeout;
throw std::runtime_error(strerror(err));
}
template <class Duration, class Predicate>
bool wait_until(std::unique_lock<const P2WMutex> &lock, const std::chrono::time_point<std::chrono::system_clock, Duration> &abs_time, Predicate pred)
{
struct timespec ts;
p2w_time_point_to_timespec(abs_time, ts);
while (!pred())
{
const int err = pthread_cond_timedwait(&native, (pthread_mutex_t *)&lock.mutex()->native, &ts);
if (likely(err == 0))
continue;
if (likely(err == ETIMEDOUT))
return false;
throw std::runtime_error(strerror(err));
}
return true;
}
template <class Rep, class Period>
std::cv_status wait_for(std::unique_lock<const P2WMutex> &lock, const std::chrono::duration<Rep, Period> &rel_time)
{
return wait_until(lock, std::chrono::system_clock::now() + rel_time);
}
template <class Rep, class Period, class Predicate>
bool wait_for(std::unique_lock<const P2WMutex> &lock, const std::chrono::duration<Rep, Period> &rel_time, Predicate pred)
{
return wait_until(lock, std::chrono::system_clock::now() + rel_time, pred);
}
pthread_cond_t *native_handle() { return &native; }
};
static_assert(sizeof(pthread_cond_t) == sizeof(P2WCond), "Size is not correct");
#endif
72 changes: 72 additions & 0 deletions _include/P2WSem.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#pragma once
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#define __STDC_FORMAT_MACROS

#include <semaphore.h>
#include <string.h>

#include <atomic>
#include <chrono>
#include <stdexcept>

#ifdef _P2W_GTHREADS
#include <windows.h>
#include <synchapi.h>
#include <processthreadsapi.h>
#endif

class P2WSem
{
public:
sem_t native;

public:
P2WSem(int count = 0)
{
if (sem_init(&native, 0, count) != 0)
throw std::runtime_error(strerror(errno));
}
~P2WSem()
{
sem_destroy(&native);
}
void release(std::ptrdiff_t update = 1)
{
for (intptr_t i = update; i-- > 0;)
sem_post(&native);
}
void acquire()
{
sem_wait(&native);
}
bool try_acquire()
{
return sem_trywait(&native) == 0;
}
template <class Rep, class Period>
bool try_acquire_for(const std::chrono::duration<Rep, Period> &rel_time)
{
return try_acquire_until(std::chrono::system_clock::now() + rel_time);
}
template <class Duration> // Clock could be template but cannot cast to different clocks, so ..
bool try_acquire_until(const std::chrono::time_point<std::chrono::system_clock, Duration> &abs_time)
{
struct timespec ts;
p2w_time_point_to_timespec(abs_time, ts);
return sem_timedwait(&native, &ts) == 0;
}
sem_t *native_handle() { return &native; }
// extra
bool try_acquire_until(const struct timespec *abs_timeout)
{
return sem_timedwait((sem_t *)&native, abs_timeout) == 0;
}
void acquire_rest()
{
while (try_acquire())
;
}
};
static_assert(sizeof(sem_t) == sizeof(P2WSem), "Size is not correct");
Loading