Skip to content

Commit cbdd8ea

Browse files
committed
Add IpcSharedSignal.
1 parent bcd1b7a commit cbdd8ea

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed

src/common/ipc/IpcSharedSignal.h

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*
2+
* The contents of this file are subject to the Initial
3+
* Developer's Public License Version 1.0 (the "License");
4+
* you may not use this file except in compliance with the
5+
* License. You may obtain a copy of the License at
6+
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
7+
*
8+
* Software distributed under the License is distributed AS IS,
9+
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing rights
11+
* and limitations under the License.
12+
*
13+
* The Original Code was created by Adriano dos Santos Fernandes
14+
* for the Firebird Open Source RDBMS project.
15+
*
16+
* Copyright (c) 2025 Adriano dos Santos Fernandes <[email protected]>
17+
* and all contributors signed below.
18+
*
19+
* All Rights Reserved.
20+
* Contributor(s): ______________________________________.
21+
*/
22+
23+
#ifndef COMMON_IPC_SHARED_SIGNAL_H
24+
#define COMMON_IPC_SHARED_SIGNAL_H
25+
26+
#include "firebird.h"
27+
28+
#ifdef WIN_NT
29+
#error This is not supported in Windows.
30+
#endif
31+
32+
#ifndef PTHREAD_PROCESS_SHARED
33+
#error Your system must support PTHREAD_PROCESS_SHARED to use firebird.
34+
#endif
35+
36+
#include "../StatusArg.h"
37+
#include "../common/os/mac_utils.h"
38+
#include "../utils_proto.h"
39+
#include <chrono>
40+
#include "fb_pthread.h"
41+
42+
namespace Firebird {
43+
44+
45+
class IpcSharedSignal
46+
{
47+
public:
48+
explicit IpcSharedSignal();
49+
~IpcSharedSignal();
50+
51+
IpcSharedSignal(const IpcSharedSignal&) = delete;
52+
IpcSharedSignal& operator=(const IpcSharedSignal&) = delete;
53+
54+
public:
55+
void reset();
56+
void signal();
57+
bool wait(std::chrono::microseconds timeout);
58+
59+
private:
60+
pthread_mutex_t mutex[1];
61+
pthread_cond_t cond[1];
62+
std::atomic_uint8_t flag = 0;
63+
};
64+
65+
66+
inline IpcSharedSignal::IpcSharedSignal()
67+
{
68+
pthread_mutexattr_t mattr;
69+
pthread_condattr_t cattr;
70+
71+
if (pthread_mutexattr_init(&mattr) != 0)
72+
system_error::raise("pthread_mutexattr_init");
73+
74+
if (pthread_condattr_init(&cattr) != 0)
75+
system_error::raise("pthread_condattr_init");
76+
77+
if (!isSandboxed())
78+
{
79+
if (pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED) != 0)
80+
system_error::raise("pthread_mutexattr_setpshared");
81+
82+
if (pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED) != 0)
83+
system_error::raise("pthread_condattr_setpshared");
84+
}
85+
86+
if (pthread_mutex_init(mutex, &mattr) != 0)
87+
system_error::raise("pthread_mutex_init");
88+
89+
if (pthread_cond_init(cond, &cattr) != 0)
90+
system_error::raise("pthread_cond_init");
91+
92+
if (pthread_mutexattr_destroy(&mattr) != 0)
93+
system_error::raise("pthread_mutexattr_destroy");
94+
95+
if (pthread_condattr_destroy(&cattr) != 0)
96+
system_error::raise("pthread_condattr_destroy");
97+
}
98+
99+
inline IpcSharedSignal::~IpcSharedSignal()
100+
{
101+
pthread_mutex_destroy(mutex);
102+
pthread_cond_destroy(cond);
103+
}
104+
105+
inline void IpcSharedSignal::reset()
106+
{
107+
flag.store(0, std::memory_order_relaxed);
108+
}
109+
110+
inline void IpcSharedSignal::signal()
111+
{
112+
// FIXME: check errors
113+
114+
if (pthread_mutex_lock(mutex) != 0)
115+
system_error::raise("pthread_mutex_lock");
116+
117+
flag.store(1, std::memory_order_relaxed);
118+
const int ret = pthread_cond_broadcast(cond);
119+
pthread_mutex_unlock(mutex);
120+
121+
if (ret != 0)
122+
system_error::raise("pthread_cond_broadcast");
123+
}
124+
125+
inline bool IpcSharedSignal::wait(std::chrono::microseconds timeout)
126+
{
127+
if (flag.load(std::memory_order_acquire) == 1)
128+
return true;
129+
130+
timespec timer;
131+
132+
#if defined(HAVE_CLOCK_GETTIME)
133+
clock_gettime(CLOCK_REALTIME, &timer);
134+
#elif defined(HAVE_GETTIMEOFDAY)
135+
struct timeval tp;
136+
GETTIMEOFDAY(&tp);
137+
timer.tv_sec = tp.tv_sec;
138+
timer.tv_nsec = tp.tv_usec * 1'000;
139+
#else
140+
struct timeb time_buffer;
141+
ftime(&time_buffer);
142+
timer.tv_sec = time_buffer.time;
143+
timer.tv_nsec = time_buffer.millitm * 1'000'000;
144+
#endif
145+
146+
bool ret = true;
147+
pthread_mutex_lock(mutex);
148+
149+
do
150+
{
151+
if (flag.load(std::memory_order_relaxed) == 1)
152+
{
153+
ret = true;
154+
break;
155+
}
156+
157+
// The Posix pthread_cond_wait & pthread_cond_timedwait calls
158+
// atomically release the mutex and start a wait.
159+
// The mutex is reacquired before the call returns.
160+
const auto wait = pthread_cond_timedwait(cond, mutex, &timer);
161+
162+
if (wait == ETIMEDOUT)
163+
{
164+
// The timer expired - see if the event occurred and return
165+
ret = flag.load(std::memory_order_relaxed) == 1;
166+
break;
167+
}
168+
} while(true);
169+
170+
pthread_mutex_unlock(mutex);
171+
172+
return ret;
173+
}
174+
175+
176+
} // namespace Firebird
177+
178+
#endif // COMMON_IPC_SHARED_SIGNAL_H

0 commit comments

Comments
 (0)